Пример #1
0
        public void OnMesg(object sender, MesgEventArgs e)
        {
            // Notify any subscribers of either our general mesg event or specific profile mesg event
            if (MesgEvent != null)
            {
                MesgEvent(sender, e);
            }

            switch (e.mesg.Num)
            {
            case (ushort)MesgNum.FileId:
                if (FileIdMesgEvent != null)
                {
                    FileIdMesg    fileIdMesg    = new FileIdMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = fileIdMesg;
                    FileIdMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.FileCreator:
                if (FileCreatorMesgEvent != null)
                {
                    FileCreatorMesg fileCreatorMesg = new FileCreatorMesg(e.mesg);
                    MesgEventArgs   mesgEventArgs   = new MesgEventArgs();
                    mesgEventArgs.mesg = fileCreatorMesg;
                    FileCreatorMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Software:
                if (SoftwareMesgEvent != null)
                {
                    SoftwareMesg  softwareMesg  = new SoftwareMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = softwareMesg;
                    SoftwareMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.SlaveDevice:
                if (SlaveDeviceMesgEvent != null)
                {
                    SlaveDeviceMesg slaveDeviceMesg = new SlaveDeviceMesg(e.mesg);
                    MesgEventArgs   mesgEventArgs   = new MesgEventArgs();
                    mesgEventArgs.mesg = slaveDeviceMesg;
                    SlaveDeviceMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Capabilities:
                if (CapabilitiesMesgEvent != null)
                {
                    CapabilitiesMesg capabilitiesMesg = new CapabilitiesMesg(e.mesg);
                    MesgEventArgs    mesgEventArgs    = new MesgEventArgs();
                    mesgEventArgs.mesg = capabilitiesMesg;
                    CapabilitiesMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.FileCapabilities:
                if (FileCapabilitiesMesgEvent != null)
                {
                    FileCapabilitiesMesg fileCapabilitiesMesg = new FileCapabilitiesMesg(e.mesg);
                    MesgEventArgs        mesgEventArgs        = new MesgEventArgs();
                    mesgEventArgs.mesg = fileCapabilitiesMesg;
                    FileCapabilitiesMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.MesgCapabilities:
                if (MesgCapabilitiesMesgEvent != null)
                {
                    MesgCapabilitiesMesg mesgCapabilitiesMesg = new MesgCapabilitiesMesg(e.mesg);
                    MesgEventArgs        mesgEventArgs        = new MesgEventArgs();
                    mesgEventArgs.mesg = mesgCapabilitiesMesg;
                    MesgCapabilitiesMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.FieldCapabilities:
                if (FieldCapabilitiesMesgEvent != null)
                {
                    FieldCapabilitiesMesg fieldCapabilitiesMesg = new FieldCapabilitiesMesg(e.mesg);
                    MesgEventArgs         mesgEventArgs         = new MesgEventArgs();
                    mesgEventArgs.mesg = fieldCapabilitiesMesg;
                    FieldCapabilitiesMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.DeviceSettings:
                if (DeviceSettingsMesgEvent != null)
                {
                    DeviceSettingsMesg deviceSettingsMesg = new DeviceSettingsMesg(e.mesg);
                    MesgEventArgs      mesgEventArgs      = new MesgEventArgs();
                    mesgEventArgs.mesg = deviceSettingsMesg;
                    DeviceSettingsMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.UserProfile:
                if (UserProfileMesgEvent != null)
                {
                    UserProfileMesg userProfileMesg = new UserProfileMesg(e.mesg);
                    MesgEventArgs   mesgEventArgs   = new MesgEventArgs();
                    mesgEventArgs.mesg = userProfileMesg;
                    UserProfileMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.HrmProfile:
                if (HrmProfileMesgEvent != null)
                {
                    HrmProfileMesg hrmProfileMesg = new HrmProfileMesg(e.mesg);
                    MesgEventArgs  mesgEventArgs  = new MesgEventArgs();
                    mesgEventArgs.mesg = hrmProfileMesg;
                    HrmProfileMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.SdmProfile:
                if (SdmProfileMesgEvent != null)
                {
                    SdmProfileMesg sdmProfileMesg = new SdmProfileMesg(e.mesg);
                    MesgEventArgs  mesgEventArgs  = new MesgEventArgs();
                    mesgEventArgs.mesg = sdmProfileMesg;
                    SdmProfileMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.BikeProfile:
                if (BikeProfileMesgEvent != null)
                {
                    BikeProfileMesg bikeProfileMesg = new BikeProfileMesg(e.mesg);
                    MesgEventArgs   mesgEventArgs   = new MesgEventArgs();
                    mesgEventArgs.mesg = bikeProfileMesg;
                    BikeProfileMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.ZonesTarget:
                if (ZonesTargetMesgEvent != null)
                {
                    ZonesTargetMesg zonesTargetMesg = new ZonesTargetMesg(e.mesg);
                    MesgEventArgs   mesgEventArgs   = new MesgEventArgs();
                    mesgEventArgs.mesg = zonesTargetMesg;
                    ZonesTargetMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Sport:
                if (SportMesgEvent != null)
                {
                    SportMesg     sportMesg     = new SportMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = sportMesg;
                    SportMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.HrZone:
                if (HrZoneMesgEvent != null)
                {
                    HrZoneMesg    hrZoneMesg    = new HrZoneMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = hrZoneMesg;
                    HrZoneMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.SpeedZone:
                if (SpeedZoneMesgEvent != null)
                {
                    SpeedZoneMesg speedZoneMesg = new SpeedZoneMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = speedZoneMesg;
                    SpeedZoneMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.CadenceZone:
                if (CadenceZoneMesgEvent != null)
                {
                    CadenceZoneMesg cadenceZoneMesg = new CadenceZoneMesg(e.mesg);
                    MesgEventArgs   mesgEventArgs   = new MesgEventArgs();
                    mesgEventArgs.mesg = cadenceZoneMesg;
                    CadenceZoneMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.PowerZone:
                if (PowerZoneMesgEvent != null)
                {
                    PowerZoneMesg powerZoneMesg = new PowerZoneMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = powerZoneMesg;
                    PowerZoneMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.MetZone:
                if (MetZoneMesgEvent != null)
                {
                    MetZoneMesg   metZoneMesg   = new MetZoneMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = metZoneMesg;
                    MetZoneMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Goal:
                if (GoalMesgEvent != null)
                {
                    GoalMesg      goalMesg      = new GoalMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = goalMesg;
                    GoalMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Activity:
                if (ActivityMesgEvent != null)
                {
                    ActivityMesg  activityMesg  = new ActivityMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = activityMesg;
                    ActivityMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Session:
                if (SessionMesgEvent != null)
                {
                    SessionMesg   sessionMesg   = new SessionMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = sessionMesg;
                    SessionMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Lap:
                if (LapMesgEvent != null)
                {
                    LapMesg       lapMesg       = new LapMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = lapMesg;
                    LapMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Length:
                if (LengthMesgEvent != null)
                {
                    LengthMesg    lengthMesg    = new LengthMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = lengthMesg;
                    LengthMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Record:
                if (RecordMesgEvent != null)
                {
                    RecordMesg    recordMesg    = new RecordMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = recordMesg;
                    RecordMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Event:
                if (EventMesgEvent != null)
                {
                    EventMesg     eventMesg     = new EventMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = eventMesg;
                    EventMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.DeviceInfo:
                if (DeviceInfoMesgEvent != null)
                {
                    DeviceInfoMesg deviceInfoMesg = new DeviceInfoMesg(e.mesg);
                    MesgEventArgs  mesgEventArgs  = new MesgEventArgs();
                    mesgEventArgs.mesg = deviceInfoMesg;
                    DeviceInfoMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.TrainingFile:
                if (TrainingFileMesgEvent != null)
                {
                    TrainingFileMesg trainingFileMesg = new TrainingFileMesg(e.mesg);
                    MesgEventArgs    mesgEventArgs    = new MesgEventArgs();
                    mesgEventArgs.mesg = trainingFileMesg;
                    TrainingFileMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Hrv:
                if (HrvMesgEvent != null)
                {
                    HrvMesg       hrvMesg       = new HrvMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = hrvMesg;
                    HrvMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Course:
                if (CourseMesgEvent != null)
                {
                    CourseMesg    courseMesg    = new CourseMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = courseMesg;
                    CourseMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.CoursePoint:
                if (CoursePointMesgEvent != null)
                {
                    CoursePointMesg coursePointMesg = new CoursePointMesg(e.mesg);
                    MesgEventArgs   mesgEventArgs   = new MesgEventArgs();
                    mesgEventArgs.mesg = coursePointMesg;
                    CoursePointMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Workout:
                if (WorkoutMesgEvent != null)
                {
                    WorkoutMesg   workoutMesg   = new WorkoutMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = workoutMesg;
                    WorkoutMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.WorkoutStep:
                if (WorkoutStepMesgEvent != null)
                {
                    WorkoutStepMesg workoutStepMesg = new WorkoutStepMesg(e.mesg);
                    MesgEventArgs   mesgEventArgs   = new MesgEventArgs();
                    mesgEventArgs.mesg = workoutStepMesg;
                    WorkoutStepMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Schedule:
                if (ScheduleMesgEvent != null)
                {
                    ScheduleMesg  scheduleMesg  = new ScheduleMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = scheduleMesg;
                    ScheduleMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Totals:
                if (TotalsMesgEvent != null)
                {
                    TotalsMesg    totalsMesg    = new TotalsMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = totalsMesg;
                    TotalsMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.WeightScale:
                if (WeightScaleMesgEvent != null)
                {
                    WeightScaleMesg weightScaleMesg = new WeightScaleMesg(e.mesg);
                    MesgEventArgs   mesgEventArgs   = new MesgEventArgs();
                    mesgEventArgs.mesg = weightScaleMesg;
                    WeightScaleMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.BloodPressure:
                if (BloodPressureMesgEvent != null)
                {
                    BloodPressureMesg bloodPressureMesg = new BloodPressureMesg(e.mesg);
                    MesgEventArgs     mesgEventArgs     = new MesgEventArgs();
                    mesgEventArgs.mesg = bloodPressureMesg;
                    BloodPressureMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.MonitoringInfo:
                if (MonitoringInfoMesgEvent != null)
                {
                    MonitoringInfoMesg monitoringInfoMesg = new MonitoringInfoMesg(e.mesg);
                    MesgEventArgs      mesgEventArgs      = new MesgEventArgs();
                    mesgEventArgs.mesg = monitoringInfoMesg;
                    MonitoringInfoMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Monitoring:
                if (MonitoringMesgEvent != null)
                {
                    MonitoringMesg monitoringMesg = new MonitoringMesg(e.mesg);
                    MesgEventArgs  mesgEventArgs  = new MesgEventArgs();
                    mesgEventArgs.mesg = monitoringMesg;
                    MonitoringMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.MemoGlob:
                if (MemoGlobMesgEvent != null)
                {
                    MemoGlobMesg  memoGlobMesg  = new MemoGlobMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = memoGlobMesg;
                    MemoGlobMesgEvent(sender, mesgEventArgs);
                }
                break;

            case (ushort)MesgNum.Pad:
                if (PadMesgEvent != null)
                {
                    PadMesg       padMesg       = new PadMesg(e.mesg);
                    MesgEventArgs mesgEventArgs = new MesgEventArgs();
                    mesgEventArgs.mesg = padMesg;
                    PadMesgEvent(sender, mesgEventArgs);
                }
                break;
            }
        }
Пример #2
0
        static void Main(string[] args)
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            // Generate some FIT messages
            FileIdMesg fileIdMesg = new FileIdMesg();

            fileIdMesg.SetManufacturer(Manufacturer.Dynastream);  // Types defined in the profile are available
            fileIdMesg.SetProduct(1000);
            fileIdMesg.SetSerialNumber(12345);

            //UserProfileMesg myUserProfile = new UserProfileMesg();
            //myUserProfile.SetGender(Gender.Female);
            //float myWeight = 63.1F;
            //myUserProfile.SetWeight(myWeight);
            //myUserProfile.SetAge(99);
            //myUserProfile.SetFriendlyName(Encoding.UTF8.GetBytes("TestUser"));

            var route = GpxClass.FromFile("route.gpx");

            CourseMesg course = new CourseMesg();

            course.SetName(Encoding.UTF8.GetBytes("route from gpx"));
            course.SetSport(Sport.Cycling);

            var baseDate = route.metadata.timeSpecified ? route.metadata.time : System.DateTime.Now.AddDays(-1);

            FileStream fitDest = new FileStream("Test.fit", FileMode.Create, FileAccess.ReadWrite, FileShare.Read);

            // Create file encode object
            Encode encodeDemo = new Encode();

            // Write our header
            encodeDemo.Open(fitDest);
            // Encode each message, a definition message is automatically generated and output if necessary
            encodeDemo.Write(fileIdMesg);
            //encodeDemo.Write(myUserProfile);

            encodeDemo.Write(course);

            var lap = new LapMesg();

            encodeDemo.Write(lap);


            var firstTrk = route.trk.First();

            var firstTrkSeg = firstTrk.trkseg.First();

            var firstPoint = firstTrkSeg.trkpt.First();

            lap.SetTimestamp(new fit.DateTime(firstPoint.time));
            lap.SetStartPositionLat(firstPoint.lat.RawInt());
            lap.SetStartPositionLong(firstPoint.lon.RawInt());

            var lastPoint = firstTrkSeg.trkpt.Last();

            lap.SetEndPositionLat(lastPoint.lat.RawInt());
            lap.SetEndPositionLong(lastPoint.lon.RawInt());

            var e = new EventMesg();

            e.SetTimestamp(new fit.DateTime(firstPoint.time));
            e.SetEventType(EventType.Start);
            e.SetEventGroup(0);
            e.SetEvent(Event.Timer);
            e.SetData(null);
            encodeDemo.Write(e);

            foreach (var point in firstTrkSeg.trkpt)
            {
                var p = new RecordMesg();
                p.SetPositionLat(point.lat.RawInt());
                p.SetPositionLong(point.lon.RawInt());
                //p.SetDistance(point. 10665.65f);
                p.SetAltitude(Convert.ToSingle(point.ele));
                p.SetTimestamp(new fit.DateTime(baseDate));

                encodeDemo.Write(p);
            }

            var eventStop = new EventMesg();

            eventStop.SetData(null);
            eventStop.SetTimestamp(new fit.DateTime(lastPoint.time));
            eventStop.SetEvent(Event.Timer);
            eventStop.SetEventType(EventType.StopDisableAll);
            encodeDemo.Write(eventStop);

            // Update header datasize and file CRC
            encodeDemo.Close();

            fitDest.Close();

            Console.WriteLine("Encoded FIT file test.fit");
            stopwatch.Stop();
            Console.WriteLine("Time elapsed: {0:0.#}s", stopwatch.Elapsed.TotalSeconds);

            Console.ReadKey();
        }
Пример #3
0
        public static void EncodeCourse()
        {
            const string filename = "CourseEncodeRecipe.fit";

            // Example Record Data Defining a Course
            var courseData = new List <Dictionary <string, object> >()
            {
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262849U }, { "position_lat", 463583114 }, { "position_long", -1131028903 }, { "altitude", 329f }, { "distance", 0f }, { "speed", 0f }
                },
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262855U }, { "position_lat", 463583127 }, { "position_long", -1131031938 }, { "altitude", 328.6f }, { "distance", 22.03f }, { "speed", 3.0f }
                },
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262869U }, { "position_lat", 463583152 }, { "position_long", -1131038159 }, { "altitude", 327.6f }, { "distance", 67.29f }, { "speed", 3.0f }
                },
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262876U }, { "position_lat", 463583164 }, { "position_long", -1131041346 }, { "altitude", 327f }, { "distance", 90.52f }, { "speed", 3.0f }
                },
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262876U }, { "position_lat", 463583164 }, { "position_long", -1131041319 }, { "altitude", 327f }, { "distance", 90.72f }, { "speed", 3.0f }
                },
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262891U }, { "position_lat", 463588537 }, { "position_long", -1131041383 }, { "altitude", 327f }, { "distance", 140.72f }, { "speed", 3.0f }
                },
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262891U }, { "position_lat", 463588549 }, { "position_long", -1131041383 }, { "altitude", 327f }, { "distance", 140.82f }, { "speed", 3.0f }
                },
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262897U }, { "position_lat", 463588537 }, { "position_long", -1131038293 }, { "altitude", 327.6f }, { "distance", 163.26f }, { "speed", 3.0f }
                },
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262911U }, { "position_lat", 463588512 }, { "position_long", -1131032041 }, { "altitude", 328.4f }, { "distance", 208.75f }, { "speed", 3.0f }
                },
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262918U }, { "position_lat", 463588499 }, { "position_long", -1131028879 }, { "altitude", 329f }, { "distance", 231.8f }, { "speed", 3.0f }
                },
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262918U }, { "position_lat", 463588499 }, { "position_long", -1131028903 }, { "altitude", 329f }, { "distance", 231.97f }, { "speed", 3.0f }
                },
                new Dictionary <string, object>()
                {
                    { "timestamp", 961262933U }, { "position_lat", 463583127 }, { "position_long", -1131028903 }, { "altitude", 329f }, { "distance", 281.96f }, { "speed", 3.0f }
                },
            };

            // Create the output stream, this can be any type of stream, including a file or memory stream. Must have read/write access.
            FileStream fitDest = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);

            // Create a FIT Encode object
            Encode encoder = new Encode(ProtocolVersion.V10);

            // Write the FIT header to the output stream
            encoder.Open(fitDest);

            // Reference points for the course
            var firstRecord    = courseData[0];
            var lastRecord     = courseData[courseData.Count - 1];
            var halfwayRecord  = courseData[courseData.Count / 2];
            var startTimestamp = (uint)firstRecord["timestamp"];
            var endTimestamp   = (uint)lastRecord["timestamp"];
            var startDateTime  = new Dynastream.Fit.DateTime(startTimestamp);
            var endDateTime    = new Dynastream.Fit.DateTime(endTimestamp);

            // Every FIT file MUST contain a File ID message
            var fileIdMesg = new FileIdMesg();

            fileIdMesg.SetType(Dynastream.Fit.File.Course);
            fileIdMesg.SetManufacturer(Manufacturer.Development);
            fileIdMesg.SetProduct(ProductId);
            fileIdMesg.SetTimeCreated(startDateTime);
            fileIdMesg.SetSerialNumber(startDateTime.GetTimeStamp());
            encoder.Write(fileIdMesg);

            // Every FIT file MUST contain a Course message
            var courseMesg = new CourseMesg();

            courseMesg.SetName("Garmin Field Day");
            courseMesg.SetSport(Sport.Cycling);
            encoder.Write(courseMesg);

            // Every FIT COURSE file MUST contain a Lap message
            var lapMesg = new LapMesg();

            lapMesg.SetStartTime(startDateTime);
            lapMesg.SetTimestamp(startDateTime);
            lapMesg.SetTotalElapsedTime(endTimestamp - startTimestamp);
            lapMesg.SetTotalTimerTime(endTimestamp - startTimestamp);
            lapMesg.SetStartPositionLat((int)firstRecord["position_lat"]);
            lapMesg.SetStartPositionLong((int)firstRecord["position_long"]);
            lapMesg.SetEndPositionLat((int)lastRecord["position_lat"]);
            lapMesg.SetEndPositionLong((int)lastRecord["position_long"]);
            lapMesg.SetTotalDistance((float)lastRecord["distance"]);
            encoder.Write(lapMesg);

            // Timer Events are REQUIRED for FIT COURSE files
            var eventMesgStart = new EventMesg();

            eventMesgStart.SetTimestamp(startDateTime);
            eventMesgStart.SetEvent(Event.Timer);
            eventMesgStart.SetEventType(EventType.Start);
            encoder.Write(eventMesgStart);

            // Every FIT COURSE file MUST contain Record messages
            foreach (var record in courseData)
            {
                var timestamp = (uint)record["timestamp"];
                var latitude  = (int)record["position_lat"];
                var longitude = (int)record["position_long"];
                var distance  = (float)record["distance"];
                var speed     = (float)record["speed"];
                var altitude  = (float)record["altitude"];

                var recordMesg = new RecordMesg();
                recordMesg.SetTimestamp(new Dynastream.Fit.DateTime(timestamp));
                recordMesg.SetPositionLat(latitude);
                recordMesg.SetPositionLong(longitude);
                recordMesg.SetDistance(distance);
                recordMesg.SetSpeed(speed);
                recordMesg.SetAltitude(altitude);
                encoder.Write(recordMesg);

                // Add a Course Point at the halfway point of the route
                if (record == halfwayRecord)
                {
                    var coursePointMesg = new CoursePointMesg();
                    coursePointMesg.SetTimestamp(new Dynastream.Fit.DateTime(timestamp));
                    coursePointMesg.SetName("Halfway");
                    coursePointMesg.SetType(CoursePoint.Generic);
                    coursePointMesg.SetPositionLat(latitude);
                    coursePointMesg.SetPositionLong(longitude);
                    coursePointMesg.SetDistance(distance);
                    encoder.Write(coursePointMesg);
                }
            }

            // Timer Events are REQUIRED for FIT COURSE files
            var eventMesgStop = new EventMesg();

            eventMesgStop.SetTimestamp(endDateTime);
            eventMesgStop.SetEvent(Event.Timer);
            eventMesgStop.SetEventType(EventType.StopAll);
            encoder.Write(eventMesgStop);

            // Update the data size in the header and calculate the CRC
            encoder.Close();

            // Close the output stream
            fitDest.Close();

            Console.WriteLine($"Encoded FIT file {fitDest.Name}");
        }