private void MergeFiles(Stream outStream) { lock (_zwiftFile) { ResetStreams(); FindDelay(); _encode = new Encode(outStream, ProtocolVersion.V20); try { ResetStreams(); // Read the header from both files to ensure we can step through the messages MergeMessages(); } finally { _encode.Close(); _encode = null; ResetStreams(); } } outStream.Seek(0, SeekOrigin.Begin); }
public static void Stop() { var now = new DateTime(System.DateTime.Now); TerminateLap(); sessionMesg.SetTimestamp(now); sessionMesg.SetSport(Sport.Cycling); sessionMesg.SetSubSport(SubSport.VirtualActivity); sessionMesg.SetTotalDistance(State.TripTotalKm * 1000); sessionMesg.SetTotalElapsedTime(State.TripTotalTime); sessionMesg.SetFirstLapIndex(0); sessionMesg.SetNumLaps(numLaps); sessionMesg.SetEvent(Event.Session); sessionMesg.SetEventType(EventType.Stop); sessionMesg.SetEventGroup(0); activityMesg = new ActivityMesg(); activityMesg.SetTimestamp(now); activityMesg.SetTotalTimerTime(State.TripTotalTime); activityMesg.SetNumSessions(1); activityMesg.SetType(Activity.Manual); activityMesg.SetEvent(Event.Activity); activityMesg.SetEventType(EventType.Stop); activityMesg.SetEventGroup(0); encoder.Write(sessionMesg); encoder.Write(activityMesg); encoder.Close(); fitDest.Close(); }
public void Close() { if (_encoder != null) { _encoder.Close(); _encoder = null; } }
static void CreateActivityFile(List <Mesg> messages, String filename, Dynastream.Fit.DateTime startTime) { // The combination of file type, manufacturer id, product id, and serial number should be unique. // When available, a non-random serial number should be used. Dynastream.Fit.File fileType = Dynastream.Fit.File.Activity; ushort manufacturerId = Manufacturer.Development; ushort productId = 0; float softwareVersion = 1.0f; Random random = new Random(); uint serialNumber = (uint)random.Next(); // Every FIT file MUST contain a File ID message var fileIdMesg = new FileIdMesg(); fileIdMesg.SetType(fileType); fileIdMesg.SetManufacturer(manufacturerId); fileIdMesg.SetProduct(productId); fileIdMesg.SetTimeCreated(startTime); fileIdMesg.SetSerialNumber(serialNumber); // A Device Info message is a BEST PRACTICE for FIT ACTIVITY files var deviceInfoMesg = new DeviceInfoMesg(); deviceInfoMesg.SetDeviceIndex(DeviceIndex.Creator); deviceInfoMesg.SetManufacturer(Manufacturer.Development); deviceInfoMesg.SetProduct(productId); deviceInfoMesg.SetProductName("FIT Cookbook"); // Max 20 Chars deviceInfoMesg.SetSerialNumber(serialNumber); deviceInfoMesg.SetSoftwareVersion(softwareVersion); deviceInfoMesg.SetTimestamp(startTime); // 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.V20); // Write the FIT header to the output stream encoder.Open(fitDest); // Write the messages to the file, in the proper sequence encoder.Write(fileIdMesg); encoder.Write(deviceInfoMesg); foreach (Mesg message in messages) { encoder.Write(message); } // 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}"); }
private void convertFilesGarmin() { int result; string gcUploadFileName = "GCupload.fit"; HttpGarmin garminUpload = new HttpGarmin(txtGarminUsername.Text, txtGarminPassword.Text, gcUploadFileName); result = garminUpload.GarminLogin(); foreach (string sourceFile in Directory.GetFiles(txtSource.Text, "*.fit")) { string sourceFileName = Path.GetFileName(sourceFile); string destinationFile = txtDestination.Text + "\\" + sourceFileName; string archiveFile = txtArchive.Text + "\\" + sourceFileName; string gcUploadFile = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\" + gcUploadFileName; fitSource = new FileStream(sourceFile, FileMode.Open); Decode GD3decoder = new Decode(); MesgBroadcaster mesgBroadcaster = new MesgBroadcaster(); GD3encoder = new Encode(ProtocolVersion.V20); fitDest = new FileStream(destinationFile, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); GD3encoder.Open(fitDest); GD3decoder.MesgEvent += mesgBroadcaster.OnMesg; mesgBroadcaster.MesgEvent += OnMesg; bool status = GD3decoder.IsFIT(fitSource); status &= GD3decoder.CheckIntegrity(fitSource); if (status) { GD3decoder.Read(fitSource); } fitSource.Close(); GD3encoder.Close(); fitDest.Close(); System.IO.File.Move(sourceFile, archiveFile); System.IO.File.Copy(destinationFile, gcUploadFile, true); result = garminUpload.GarminUpload(); System.IO.File.Delete(gcUploadFile); } result = garminUpload.GarminLogout(); }
protected override void Save(Tuple <string, ICollection <Mesg> > data, string path) { using (FileStream fitDest = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) { Encode encoder = new Encode(ProtocolVersion.V20); encoder.Open(fitDest); foreach (Mesg message in data.Item2) { encoder.Write(message); } encoder.Close(); Log.Information("Encoded FIT file {@Path}", fitDest.Name); } }
//[Test] //public void DecodeFitFile() //{ // var syncMyWorkoutFitFile = Path.Join(DataDirectory, "fenix_outdoor_run_vo2.fit"); // FitDecoder.Decode(syncMyWorkoutFitFile); //} //[Test] //public async Task DownloadWorkout() //{ // var email = ""; // var password = ""; //var workoutId = "aaa6527fd5a74b7e8e2f8975c6025e60"; // var client = new ApiClient(email, password, false); // await client.InitAuthAsync(); // var workout = await client.GetWorkoutByIdAsync(workoutId); // var workoutSamples = await client.GetWorkoutSamplesByIdAsync(workoutId); // var workoutSummary = await client.GetWorkoutSummaryByIdAsync(workoutId); // dynamic data = new JObject(); // data.Workout = workout; // data.WorkoutSamples = workoutSamples; // data.WorkoutSummary = workoutSummary; // Log.Debug(data.ToString()); // SaveRawData(data, workoutId, DataDirectory); //} //[Test] //public async Task DeSerialize() //{ // var file = Path.Join(DataDirectory, "test.json"); // var _fileHandler = new IOWrapper(); // var workout = _fileHandler.DeserializeJson<P2GWorkout>(file); //} //[Test] //public async Task Convert() //{ // var file = Path.Join(DataDirectory, "lanebreaker.json"); // var autoMocker = new AutoMocker(); // var settings = new Settings(); // var fitConverter = new ConverterInstance(settings); // var messages = fitConverter.Convert(file); // var output = Path.Join(DataDirectory, "output.fit"); // SaveFit(messages, output); //} private void SaveFit(Tuple <string, ICollection <Mesg> > messages, string outputPath) { using (FileStream fitDest = new FileStream(outputPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) { Encode encoder = new Encode(ProtocolVersion.V20); try { encoder.Open(fitDest); encoder.Write(messages.Item2); } finally { encoder.Close(); } } }
static void CreateWorkout(WorkoutMesg workoutMesg, List <WorkoutStepMesg> workoutSteps) { // The combination of file type, manufacturer id, product id, and serial number should be unique. // When available, a non-random serial number should be used. Dynastream.Fit.File fileType = Dynastream.Fit.File.Workout; ushort manufacturerId = Manufacturer.Development; ushort productId = 0; Random random = new Random(); uint serialNumber = (uint)random.Next(); // Every FIT file MUST contain a File ID message var fileIdMesg = new FileIdMesg(); fileIdMesg.SetType(fileType); fileIdMesg.SetManufacturer(manufacturerId); fileIdMesg.SetProduct(productId); fileIdMesg.SetTimeCreated(new Dynastream.Fit.DateTime(System.DateTime.UtcNow)); fileIdMesg.SetSerialNumber(serialNumber); // 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($"{workoutMesg.GetWktNameAsString().Replace(' ', '_')}.fit", 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); // Write the messages to the file, in the proper sequence encoder.Write(fileIdMesg); encoder.Write(workoutMesg); foreach (WorkoutStepMesg workoutStep in workoutSteps) { encoder.Write(workoutStep); } // 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}"); }
public static void Stop(DateTime?time = null) { Trace.TraceInformation("Stop()"); var now = time ?? DateTime.UtcNow; TerminateLap(time); if (!isPaused) { Pause(time); } sessionMesg.SetTimestamp(new Dynastream.Fit.DateTime(now)); sessionMesg.SetSport(Sport.Cycling); sessionMesg.SetSubSport(SubSport.VirtualActivity); sessionMesg.SetTotalDistance(totalDistance); sessionMesg.SetTotalElapsedTime((float)(now - startTime).TotalSeconds); sessionMesg.SetTotalTimerTime((float)totalTimerTime.TotalSeconds); sessionMesg.SetFirstLapIndex(0); sessionMesg.SetNumLaps(numLaps); sessionMesg.SetEvent(Event.Session); sessionMesg.SetEventType(EventType.Stop); sessionMesg.SetEventGroup(0); sessionMesg.SetStartTime(new Dynastream.Fit.DateTime(startTime)); activityMesg = new ActivityMesg(); activityMesg.SetTimestamp(new Dynastream.Fit.DateTime(now)); activityMesg.SetTotalTimerTime((float)totalTimerTime.TotalSeconds); activityMesg.SetNumSessions(1); activityMesg.SetType(Activity.Manual); activityMesg.SetEvent(Event.Activity); activityMesg.SetEventType(EventType.Stop); activityMesg.SetEventGroup(0); encoder.Write(sessionMesg); encoder.Write(activityMesg); encoder.Close(); fitDest.Close(); csvFile.Close(); }
protected override void Save(Tuple <string, ICollection <Mesg> > data, string path) { using var tracing = Tracing.Trace($"{nameof(FitConverter)}.{nameof(Save)}") .WithTag(TagKey.Format, FileFormat.Fit.ToString()); using (FileStream fitDest = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) { Encode encoder = new Encode(ProtocolVersion.V20); try { encoder.Open(fitDest); encoder.Write(data.Item2); } finally { encoder.Close(); } _logger.Information("[{@Format}] Encoded file {@Path}", FileFormat.Fit, fitDest.Name); } }
/// <summary> /// Demonstrate the encoding of a 'Settings File' by writing a 'Settings File' containing a 'User Profile' Message. /// This example is simpler than the 'Monitoring File' example. /// </summary> static void EncodeSettingsFile() { // Generate some FIT messages FileIdMesg fileIdMesg = new FileIdMesg(); // Every FIT file MUST contain a 'File ID' message as the first message fileIdMesg.SetType(Dynastream.Fit.File.Settings); fileIdMesg.SetManufacturer(Manufacturer.Development); // Types defined in the profile are available fileIdMesg.SetProduct(1); 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")); FileStream fitDest = new FileStream("ExampleSettings.fit", FileMode.Create, FileAccess.ReadWrite, FileShare.Read); // Create file encode object Encode encodeDemo = new Encode(ProtocolVersion.V10); // 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); // Update header datasize and file CRC encodeDemo.Close(); fitDest.Close(); Console.WriteLine("Encoded FIT file ExampleSettings.fit"); return; }
public void Fit_Converter_Creates_Valid_Fit(string filename, PreferredLapType lapType) { var workoutPath = Path.Join(DataDirectory, $"{filename}.json"); var settings = new Settings() { Format = new Format() { Running = new Running() { PreferredLapType = lapType }, Cycling = new Cycling() { PreferredLapType = lapType } } }; var converter = new ConverterInstance(settings); var convertedMesgs = converter.ConvertForTest(workoutPath); convertedMesgs.Should().NotBeNullOrEmpty(); var dest = Path.Join(DataDirectory, $"test_output_{filename}.fit"); try { using (FileStream fitDest = new FileStream(dest, FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) { var validator = new Encode(ProtocolVersion.V20); validator.Open(fitDest); validator.Write(convertedMesgs); // validates while writing validator.Close(); } } finally { System.IO.File.Delete(dest); } }
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(); }
public void Strip(Stream input, Stream output, StripOptions options) { int time = Environment.TickCount; _options = options; // Create file encode object _encoder = new Encode(output); Decode decoder = new Decode(); //MesgBroadcaster mesgBroadcaster = new MesgBroadcaster(); // Connect the Broadcaster to our event (message) source (in this case the Decoder) decoder.MesgEvent += OnMesg; decoder.MesgDefinitionEvent += OnMesgDefn; // Subscribe to message events of interest by connecting to the Broadcaster //mesgBroadcaster.MesgEvent += OnMesg; //mesgBroadcaster.MesgDefinitionEvent += OnMesgDefn; _mesgCounts.Clear(); bool status = decoder.IsFIT(input); status &= decoder.CheckIntegrity(input); // Process the file if (status) { Log("Decoding..."); decoder.Read(input); Log("Decoded FIT file"); } else { try { Log("Integrity Check Failed."); Log("Attempting to decode..."); decoder.Read(input); } catch (FitException ex) { Log("DecodeDemo caught FitException: " + ex.Message); } } _encoder.Close(); Log("Summary:"); int totalMesgs = 0; foreach (KeyValuePair <ushort, int> pair in _mesgCounts) { Log("MesgID {0,3} Count {1}", pair.Key, pair.Value); totalMesgs += pair.Value; } Log("{0} Message Types {1} Total Messages", _mesgCounts.Count, totalMesgs); time = Environment.TickCount - time; Log("Time elapsed: {0:0.#}s", time / 1000.0f);// stopwatch.Elapsed.TotalSeconds); }
/// <summary> /// Encode to a fit file /// </summary> /// <param name="db"></param> /// <param name="outputFileName"></param> public static void EncodeActivityFile(TrainingCenterDatabase_t db, string outputFileName) { /* * string assemblyFilePath = Assembly.GetExecutingAssembly().GetName().CodeBase; * string assemblyPath = assemblyFilePath.Replace(SysPath.GetFileName(assemblyFilePath), ""); */ if (string.IsNullOrEmpty(outputFileName)) { outputFileName = "out"; } //outputFileName = assemblyPath + outputFileName; // write FIT file Encode encoder = new Encode(ProtocolVersion.V20); SysFileStream fitDest = new SysFileStream(outputFileName + ".fit", SysFileMode.Create, SysFileAccess.ReadWrite, SysFileShare.Read); // Write our header encoder.Open(fitDest); // FIT file_id message FileIdMesg fileIdMesg = new FileIdMesg(); fileIdMesg.SetType(File.Activity); // Activity File = 4 fileIdMesg.SetManufacturer(Manufacturer.Garmin); fileIdMesg.SetProduct(GarminProduct.Fr935); fileIdMesg.SetSerialNumber(3949668594); fileIdMesg.SetTimeCreated(new DateTime(db.Activities.Activity[0].Id)); // set from input file // Encode each message, a definition message is automatically generated and output if necessary encoder.OnMesgDefinition(new MesgDefinition(fileIdMesg)); encoder.OnMesg(fileIdMesg); Utils.LogMessage(LogType.Information, "Wrote FileID"); // FIT FileCreator FileCreatorMesg fileCreatorMesg = new FileCreatorMesg(); fileCreatorMesg.SetSoftwareVersion(600); // Garmin Connect encoder.OnMesgDefinition(new MesgDefinition(fileCreatorMesg)); encoder.OnMesg(fileCreatorMesg); Utils.LogMessage(LogType.Information, "Wrote FileCreatorMesg"); // FIT event message : not found in TCX EventMesg eventMesg = new EventMesg(); eventMesg.SetTimestamp(new DateTime(db.Activities.Activity[0].Id)); eventMesg.SetData(0); eventMesg.SetEvent(Event.Timer); eventMesg.SetEventType(EventType.Start); eventMesg.SetEventGroup(0); encoder.OnMesgDefinition(new MesgDefinition(eventMesg)); encoder.OnMesg(eventMesg); Utils.LogMessage(LogType.Information, "Wrote EventMesg"); // FIT deviceInfo message: not found in TCX DeviceInfoMesg devInfoMesg = new DeviceInfoMesg(); devInfoMesg.SetTimestamp(new DateTime(db.Activities.Activity[0].Id)); devInfoMesg.SetSerialNumber(3949668594); devInfoMesg.SetManufacturer(Manufacturer.Garmin); devInfoMesg.SetProduct(GarminProduct.Fr935); devInfoMesg.SetSoftwareVersion(6); devInfoMesg.SetDeviceIndex(0); devInfoMesg.SetSourceType(SourceType.Local); for (int i = 0; i < 4; i++) { encoder.OnMesgDefinition(new MesgDefinition(devInfoMesg)); encoder.OnMesg(devInfoMesg); Utils.LogMessage(LogType.Information, "Wrote DeviceInfoMesg"); } // FIT deviceSettings message: not found in TCX DeviceSettingsMesg devSettingsMesg = new DeviceSettingsMesg(); devSettingsMesg.SetUtcOffset(0); devSettingsMesg.SetTimeOffset(7, 0); devSettingsMesg.SetAutoActivityDetect(0); devSettingsMesg.SetAutosyncMinSteps(2000); devSettingsMesg.SetAutosyncMinTime(240); devSettingsMesg.SetActiveTimeZone(0); devSettingsMesg.SetActivityTrackerEnabled(Bool.True); devSettingsMesg.SetMountingSide(Side.Left); devSettingsMesg.SetTimeMode(1, TimeMode.Utc); encoder.OnMesgDefinition(new MesgDefinition(devSettingsMesg)); encoder.OnMesg(devSettingsMesg); Utils.LogMessage(LogType.Information, "Wrote DeviceSettingsMesg"); // FIT UserProfile message: : not found in TCX UserProfileMesg userProfileMesg = new UserProfileMesg(); userProfileMesg.SetActivityClass(ActivityClass.Level); encoder.OnMesgDefinition(new MesgDefinition(userProfileMesg)); encoder.OnMesg(userProfileMesg); Utils.LogMessage(LogType.Information, "Wrote UserProfileMesg"); // FIT Sport: SportMesg sportMesg = new SportMesg(); sportMesg.SetSport(Sport.Running); sportMesg.SetSubSport(SubSport.Road); // Encode each message, a definition message is automatically generated and output if necessary encoder.OnMesgDefinition(new MesgDefinition(sportMesg)); encoder.OnMesg(sportMesg); Utils.LogMessage(LogType.Information, "Wrote SportMesg"); // create FIT record and lap message double totalTime = 0; foreach (Activity_t act in db.Activities.Activity) { foreach (ActivityLap_t lap in act.Lap) { List <RecordMesg> records = new List <RecordMesg>(); // FIT Record message: foreach (Trackpoint_t trackPoint in lap.Track) { RecordMesg recMesg = new RecordMesg(); recMesg.SetTimestamp(new DateTime(trackPoint.Time)); recMesg.SetPositionLat(Utils.ConvertTcxLatLongToFit(trackPoint.Position.LatitudeDegrees)); recMesg.SetPositionLong(Utils.ConvertTcxLatLongToFit(trackPoint.Position.LongitudeDegrees)); recMesg.SetDistance((float)trackPoint.DistanceMeters); recMesg.SetAltitude((float)trackPoint.AltitudeMeters); //recMesg.SetSpeed((float)trackPoint.Extensions.Any["Speed"]); if (trackPoint.HeartRateBpm != null) { recMesg.SetHeartRate((byte)trackPoint.HeartRateBpm.Value); } // Extension if (trackPoint.Extensions.Any[0].GetElementsByTagName("ns3:RunCadence") != null) { if (trackPoint.Extensions.Any[0].GetElementsByTagName("ns3:RunCadence").Count == 1) { int cadence = 0; int.TryParse((trackPoint.Extensions.Any[0].GetElementsByTagName("ns3:RunCadence")[0].InnerText), out cadence); recMesg.SetCadence((byte)cadence); } } if (trackPoint.Extensions.Any[0].GetElementsByTagName("ns3:Speed") != null) { if (trackPoint.Extensions.Any[0].GetElementsByTagName("ns3:Speed").Count == 1) { double speed = 0; double.TryParse((trackPoint.Extensions.Any[0].GetElementsByTagName("ns3:Speed")[0].InnerText), out speed); recMesg.SetSpeed((float)speed); } } encoder.OnMesgDefinition(new MesgDefinition(recMesg)); encoder.OnMesg(recMesg); Utils.LogMessage(LogType.Information, string.Format("Wrote RecMesg: {0}", recMesg.GetTimestamp().ToString())); } LapMesg lapMesg = new LapMesg(); lapMesg.SetTimestamp(new DateTime(lap.StartTime)); lapMesg.SetStartTime(new DateTime(lap.StartTime)); lapMesg.SetTotalMovingTime((float)lap.TotalTimeSeconds); lapMesg.SetStartPositionLat(Utils.ConvertTcxLatLongToFit(lap.Track[0].Position.LatitudeDegrees)); lapMesg.SetStartPositionLong(Utils.ConvertTcxLatLongToFit(lap.Track[0].Position.LongitudeDegrees)); lapMesg.SetSport(Sport.Running); lapMesg.SetSubSport(SubSport.Road); // TODO: EndPosition lapMesg.SetTotalElapsedTime((float)lap.TotalTimeSeconds); totalTime += lap.TotalTimeSeconds; // TODO: The rest encoder.OnMesgDefinition(new MesgDefinition(lapMesg)); encoder.OnMesg(lapMesg); Utils.LogMessage(LogType.Information, "Wrote LapMesg"); } } // FIT Session: not found in tcx // FIT Activity ActivityMesg activityMesg = new ActivityMesg(); activityMesg.SetTimestamp(new DateTime(db.Activities.Activity[0].Id)); activityMesg.SetTotalTimerTime((float)totalTime); activityMesg.SetLocalTimestamp(new DateTime(db.Activities.Activity[0].Id).GetTimeStamp() + (uint)totalTime); activityMesg.SetNumSessions(1); activityMesg.SetType(Activity.Manual); activityMesg.SetEvent(Event.Activity); activityMesg.SetEventType(EventType.Stop); //activityMesg.SetTotalTimerTime(db.Activities.Activity[0].Training.); encoder.OnMesgDefinition(new MesgDefinition(activityMesg)); encoder.OnMesg(activityMesg); Utils.LogMessage(LogType.Information, "Wrote ActivityMesg"); // Update header datasize and file CRC encoder.Close(); fitDest.Close(); Console.WriteLine("Encoded FIT file " + outputFileName + ".fit"); }
/// <summary> /// Writes the data to a FIT file. /// </summary> /// <param name="fileName">Name of the FIT file to write to.</param> /// <param name="start">Start date/time of the activity.</param> /// <param name="laps">Lap and record data to be written.</param> /// <param name="calories">Calories used for the activity.</param> /// <param name="work">Work done for the activity.</param> static void WriteFitFile(string fileName, System.DateTime start, LapsList laps, int calories, uint work) { // open the encoder and stream Encode encoder = new Encode(ProtocolVersion.V20); FileStream fitStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); encoder.Open(fitStream); // write the file ID message FileIdMesg fileIdMsg = new FileIdMesg(); fileIdMsg.SetType(Dynastream.Fit.File.Activity); fileIdMsg.SetManufacturer(Manufacturer.StagesCycling); fileIdMsg.SetProduct(3); fileIdMsg.SetSerialNumber(1); fileIdMsg.SetTimeCreated(new Dynastream.Fit.DateTime(start)); encoder.Write(fileIdMsg); // write the record and lap messages foreach (Lap lap in laps) { // write the record messages foreach (Record record in lap.Records) { RecordMesg recordMsg = new RecordMesg(); recordMsg.SetTimestamp(new Dynastream.Fit.DateTime(record.Time.ToUniversalTime())); recordMsg.SetHeartRate((byte)record.HeartRate); recordMsg.SetCadence((byte)record.Cadence); recordMsg.SetDistance((float)record.Distance * 1000); recordMsg.SetSpeed((float)(record.Speed / 3.6)); recordMsg.SetPower((ushort)record.Power); encoder.Write(recordMsg); } // write the lap message Record first = lap.Records[0]; Record last = lap.Records[lap.Records.Count - 1]; TimeSpan time = last.Time - first.Time; LapMesg lapMsg = new LapMesg(); lapMsg.SetTimestamp(new Dynastream.Fit.DateTime(last.Time.ToUniversalTime())); lapMsg.SetStartTime(new Dynastream.Fit.DateTime(first.Time.ToUniversalTime())); lapMsg.SetTotalElapsedTime((int)time.TotalSeconds); lapMsg.SetTotalTimerTime((int)time.TotalSeconds); lapMsg.SetTotalDistance((float)(last.Distance - first.Distance) * 1000); lapMsg.SetTotalCalories((ushort)lap.Calories); lapMsg.SetTotalWork(lap.Work * 1000); lapMsg.SetEvent(Event.Lap); lapMsg.SetEventType(EventType.Stop); lapMsg.SetIntensity(Intensity.Active); lapMsg.SetLapTrigger(LapTrigger.Manual); lapMsg.SetSport(Sport.Cycling); Summary lapSummary = GetLapSummary(lap); lapMsg.SetAvgCadence((byte)lapSummary.AveCadence); lapMsg.SetMaxCadence((byte)lapSummary.MaxCadence); lapMsg.SetAvgHeartRate((byte)lapSummary.AveHeartRate); lapMsg.SetMaxHeartRate((byte)lapSummary.MaxHeartRate); lapMsg.SetAvgPower((ushort)lapSummary.AvePower); lapMsg.SetMaxPower((ushort)lapSummary.MaxPower); lapMsg.SetAvgSpeed((float)lapSummary.AveSpeed / 3.6f); lapMsg.SetMaxSpeed((float)lapSummary.MaxSpeed / 3.6f); encoder.Write(lapMsg); } // get the first and last records Record firstRecord = laps[0].Records[0]; Lap lastLap = laps[laps.Count - 1]; Record lastRecord = lastLap.Records[lastLap.Records.Count - 1]; TimeSpan totalTime = lastRecord.Time - firstRecord.Time; // write the session message SessionMesg sessionMsg = new SessionMesg(); sessionMsg.SetTimestamp(new Dynastream.Fit.DateTime(lastRecord.Time.ToUniversalTime())); sessionMsg.SetStartTime(new Dynastream.Fit.DateTime(firstRecord.Time.ToUniversalTime())); sessionMsg.SetTotalElapsedTime((int)totalTime.TotalSeconds); sessionMsg.SetTotalTimerTime((int)totalTime.TotalSeconds); sessionMsg.SetTotalDistance((float)(lastRecord.Distance - firstRecord.Distance) * 1000); sessionMsg.SetTotalCalories((ushort)calories); sessionMsg.SetTotalWork(work * 1000); sessionMsg.SetFirstLapIndex(0); sessionMsg.SetNumLaps((ushort)laps.Count); sessionMsg.SetEvent(Event.Session); sessionMsg.SetEventType(EventType.Stop); sessionMsg.SetSport(Sport.Cycling); sessionMsg.SetSubSport(SubSport.Spin); Summary sessionSummary = GetSessionSummary(laps); sessionMsg.SetAvgCadence((byte)sessionSummary.AveCadence); sessionMsg.SetMaxCadence((byte)sessionSummary.MaxCadence); sessionMsg.SetAvgHeartRate((byte)sessionSummary.AveHeartRate); sessionMsg.SetMaxHeartRate((byte)sessionSummary.MaxHeartRate); sessionMsg.SetAvgPower((ushort)sessionSummary.AvePower); sessionMsg.SetMaxPower((ushort)sessionSummary.MaxPower); sessionMsg.SetAvgSpeed((float)sessionSummary.AveSpeed / 3.6f); sessionMsg.SetMaxSpeed((float)sessionSummary.MaxSpeed / 3.6f); encoder.Write(sessionMsg); // write the activity message ActivityMesg activityMsg = new ActivityMesg(); activityMsg.SetTimestamp(new Dynastream.Fit.DateTime(lastRecord.Time.ToUniversalTime())); activityMsg.SetTotalTimerTime((int)totalTime.TotalSeconds); activityMsg.SetNumSessions(1); activityMsg.SetType(Activity.Manual); activityMsg.SetEvent(Event.Activity); activityMsg.SetEventType(EventType.Stop); encoder.Write(activityMsg); // close the encoder and stream encoder.Close(); fitStream.Close(); }
/// <summary> /// Demonstrates encoding a 'MonitoringB File' of a made up device which counts steps and reports the battery status of the device. /// </summary> static void EncodeMonitoringFile() { System.DateTime systemStartTime = System.DateTime.Now; System.DateTime systemTimeNow = systemStartTime; FileStream fitDest = new FileStream("ExampleMonitoringFile.fit", FileMode.Create, FileAccess.ReadWrite, FileShare.Read); // Create file encode object Encode encodeDemo = new Encode(ProtocolVersion.V10); // Write our header encodeDemo.Open(fitDest); // Generate some FIT messages FileIdMesg fileIdMesg = new FileIdMesg(); // Every FIT file MUST contain a 'File ID' message as the first message fileIdMesg.SetTimeCreated(new Dynastream.Fit.DateTime(systemTimeNow)); fileIdMesg.SetManufacturer(Manufacturer.Development); fileIdMesg.SetProduct(1); fileIdMesg.SetSerialNumber(12345); fileIdMesg.SetNumber(0); fileIdMesg.SetType(Dynastream.Fit.File.MonitoringB); // See the 'FIT FIle Types Description' document for more information about this file type. encodeDemo.Write(fileIdMesg); // Write the 'File ID Message' DeviceInfoMesg deviceInfoMesg = new DeviceInfoMesg(); deviceInfoMesg.SetTimestamp(new Dynastream.Fit.DateTime(systemTimeNow)); deviceInfoMesg.SetSerialNumber(12345); deviceInfoMesg.SetManufacturer(Manufacturer.Development); deviceInfoMesg.SetBatteryStatus(Dynastream.Fit.BatteryStatus.Good); encodeDemo.Write(deviceInfoMesg); MonitoringMesg monitoringMesg = new MonitoringMesg(); // By default, each time a new message is written the Local Message Type 0 will be redefined to match the new message. // In this case,to avoid having a definition message each time there is a DeviceInfoMesg, we can manually set the Local Message Type of the MonitoringMessage to '1'. // By doing this we avoid an additional 7 definition messages in our FIT file. monitoringMesg.LocalNum = 1; // Simulate some data Random numberOfCycles = new Random(); // Fake a number of cycles for (int i = 0; i < 4; i++) // Each of these loops represent a quarter of a day { for (int j = 0; j < 6; j++) // Each of these loops represent 1 hour { monitoringMesg.SetTimestamp(new Dynastream.Fit.DateTime(systemTimeNow)); monitoringMesg.SetActivityType(Dynastream.Fit.ActivityType.Walking); // Setting this to walking will cause Cycles to be interpretted as steps. monitoringMesg.SetCycles(monitoringMesg.GetCycles() + numberOfCycles.Next(0, 1000)); // Cycles are accumulated (i.e. must be increasing) encodeDemo.Write(monitoringMesg); systemTimeNow = systemTimeNow.AddHours(1); // Add an hour to our contrieved timestamp } deviceInfoMesg.SetTimestamp(new Dynastream.Fit.DateTime(systemTimeNow)); deviceInfoMesg.SetBatteryStatus(Dynastream.Fit.BatteryStatus.Good); // Report the battery status every quarter day encodeDemo.Write(deviceInfoMesg); } // Update header datasize and file CRC encodeDemo.Close(); fitDest.Close(); Console.WriteLine("Encoded FIT file ExampleMonitoringFile.fit"); }
public void Foo() { using (var fitDest = new FileStream("Test.fit", FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) { Encoder = new Encode(); // Write our header Encoder.Open(fitDest); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); logger.Trace("FIT Decode Example Application"); //if (args.Length != 1) //{ // logger.Trace("Usage: decode.exe <filename>"); // return; //} // Attempt to open .FIT file var fileName = "B1.fit"; fitSource = new FileStream(fileName, FileMode.Open); logger.Trace("Opening {0}", fileName); Decode decodeDemo = new Decode(); MesgBroadcaster mesgBroadcaster = new MesgBroadcaster(); // Connect the Broadcaster to our event (message) source (in this case the Decoder) decodeDemo.MesgEvent += mesgBroadcaster.OnMesg; decodeDemo.MesgDefinitionEvent += mesgBroadcaster.OnMesgDefinition; // Subscribe to message events of interest by connecting to the Broadcaster mesgBroadcaster.MesgEvent += new MesgEventHandler(OnMesg); mesgBroadcaster.MesgDefinitionEvent += new MesgDefinitionEventHandler(OnMesgDefn); mesgBroadcaster.FileIdMesgEvent += new MesgEventHandler(OnFileIDMesg); mesgBroadcaster.UserProfileMesgEvent += new MesgEventHandler(OnUserProfileMesg); bool status = decodeDemo.IsFIT(fitSource); status &= decodeDemo.CheckIntegrity(fitSource); // Process the file if (status == true) { logger.Trace("Decoding..."); decodeDemo.Read(fitSource); logger.Trace("Decoded FIT file {0}", fileName); } else { try { logger.Trace("Integrity Check Failed {0}", fileName); logger.Trace("Attempting to decode..."); decodeDemo.Read(fitSource); } catch (FitException ex) { logger.Trace("DecodeDemo caught FitException: " + ex.Message); } } fitSource.Close(); Encoder.Close(); logger.Trace(""); logger.Trace("Summary:"); int totalMesgs = 0; foreach (KeyValuePair <ushort, int> pair in mesgCounts) { logger.Trace("MesgID {0,3} Count {1}", pair.Key, pair.Value); totalMesgs += pair.Value; } logger.Trace("{0} Message Types {1} Total Messages", mesgCounts.Count, totalMesgs); stopwatch.Stop(); logger.Trace(""); logger.Trace("Time elapsed: {0:0.#}s", stopwatch.Elapsed.TotalSeconds); } Console.ReadKey(); }
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}"); }
static void RunOptionsAndReturnExitCode(Options opts) { options = opts; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); Console.WriteLine("FIT Decode Example Application"); try { fitDest = new FileStream(options.OutFile, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); Console.WriteLine("Opening Destintion {0}", options.OutFile); // Write our header encodeDemo.Open(fitDest); // Attempt to open .FIT file fitSource = new FileStream(options.InFile, FileMode.Open); Console.WriteLine("Opening Source {0}", options.InFile); Decode decodeDemo = new Decode(); MesgBroadcaster mesgBroadcaster = new MesgBroadcaster(); // Connect the Broadcaster to our event (message) source (in this case the Decoder) decodeDemo.MesgEvent += mesgBroadcaster.OnMesg; decodeDemo.MesgDefinitionEvent += mesgBroadcaster.OnMesgDefinition; //decodeDemo.DeveloperFieldDescriptionEvent += OnDeveloperFieldDescriptionEvent; // Subscribe to message events of interest by connecting to the Broadcaster mesgBroadcaster.MesgEvent += OnMesg; mesgBroadcaster.MesgDefinitionEvent += OnMesgDefn; mesgBroadcaster.FileIdMesgEvent += OnFileIDMesg; mesgBroadcaster.UserProfileMesgEvent += OnUserProfileMesg; mesgBroadcaster.MonitoringMesgEvent += OnMonitoringMessage; mesgBroadcaster.DeviceInfoMesgEvent += OnDeviceInfoMessage; mesgBroadcaster.RecordMesgEvent += OnRecordMessage; bool status = decodeDemo.IsFIT(fitSource); status &= decodeDemo.CheckIntegrity(fitSource); // Process the file if (status) { Console.WriteLine("Translating..."); decodeDemo.Read(fitSource); Console.WriteLine("Translated FIT file {0}", options.InFile); } else { try { Console.WriteLine("Integrity Check Failed {0}", options.InFile); if (decodeDemo.InvalidDataSize) { Console.WriteLine("Invalid Size Detected, Attempting to decode..."); decodeDemo.Read(fitSource); } else { Console.WriteLine("Attempting to decode by skipping the header..."); decodeDemo.Read(fitSource, DecodeMode.InvalidHeader); } } catch (FitException ex) { Console.WriteLine("Translate caught FitException: " + ex.Message); } } fitSource.Close(); // Update header datasize and file CRC encodeDemo.Close(); fitDest.Close(); Console.WriteLine(""); Console.WriteLine("Summary:"); int totalMesgs = 0; foreach (KeyValuePair <ushort, int> pair in mesgCounts) { Console.WriteLine("MesgID {0,3} Count {1}", pair.Key, pair.Value); totalMesgs += pair.Value; } Console.WriteLine("{0} Message Types {1} Total Messages", mesgCounts.Count, totalMesgs); stopwatch.Stop(); Console.WriteLine(""); Console.WriteLine("Time elapsed: {0:0.#}s", stopwatch.Elapsed.TotalSeconds); Console.ReadKey(); } catch (FitException ex) { Console.WriteLine("A FitException occurred when trying to decode the FIT file. Message: " + ex.Message); } catch (Exception ex) { Console.WriteLine("Exception occurred when trying to decode the FIT file. Message: " + ex.Message); } }
static void EncodeActivityFile() { // Generate some FIT messages var fileIdMesg = new FileIdMesg(); // Every FIT file MUST contain a 'File ID' message as the first message var developerIdMesg = new DeveloperDataIdMesg(); var fieldDescMesg = new FieldDescriptionMesg(); var records = new List <RecordMesg>(); byte[] appId = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; fileIdMesg.SetType(Dynastream.Fit.File.Activity); fileIdMesg.SetManufacturer(Manufacturer.Development); fileIdMesg.SetProduct(1); fileIdMesg.SetSerialNumber(12345); fileIdMesg.SetTimeCreated(new DateTime(621463080)); for (int i = 0; i < appId.Length; i++) { developerIdMesg.SetApplicationId(i, appId[i]); } developerIdMesg.SetDeveloperDataIndex(0); fieldDescMesg.SetDeveloperDataIndex(0); fieldDescMesg.SetFieldDefinitionNumber(0); fieldDescMesg.SetFitBaseTypeId(FitBaseType.Sint8); fieldDescMesg.SetFieldName(0, "doughnuts_earned"); fieldDescMesg.SetUnits(0, "doughnuts"); for (int i = 0; i < 3; i++) { var newRecord = new RecordMesg(); var doughnutsEarnedField = new DeveloperField(fieldDescMesg, developerIdMesg); newRecord.SetDeveloperField(doughnutsEarnedField); newRecord.SetHeartRate((byte)(140 + (i * 2))); newRecord.SetCadence((byte)(88 + (i * 2))); newRecord.SetDistance(510 + (i * 100)); newRecord.SetSpeed(2.8f + (i * 0.4f)); doughnutsEarnedField.SetValue(i + 1); records.Add(newRecord); } // Create file encode object Encode encodeDemo = new Encode(ProtocolVersion.V20); FileStream fitDest = new FileStream("ExampleActivity.fit", FileMode.Create, FileAccess.ReadWrite, FileShare.Read); // Write our header encodeDemo.Open(fitDest); // Encode each message, a definition message is automatically generated and output if necessary encodeDemo.Write(fileIdMesg); encodeDemo.Write(developerIdMesg); encodeDemo.Write(fieldDescMesg); encodeDemo.Write(records); // Update header datasize and file CRC encodeDemo.Close(); fitDest.Close(); Console.WriteLine("Encoded FIT file ExampleActivity.fit"); }
void BtnSaveFitClick(object sender, EventArgs e) { if (saveFileDlg.ShowDialog() == DialogResult.OK) { FileIdMesg fileIdMesg = new FileIdMesg(); fileIdMesg.SetManufacturer(Manufacturer.Dynastream); fileIdMesg.SetProduct(1000); fileIdMesg.SetSerialNumber(12345); FileStream fitDest = new FileStream(saveFileDlg.FileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); // create file encode object Encode encode = new Encode(); // write out header encode.Open(fitDest); // encode each message, a definition message is automatically generated and output if necessary encode.Write(fileIdMesg); SQLiteCommand cmd = new SQLiteCommand(_db); string sql; // TODO: write FIT File Summary Information here, suspect that's why GarminConnect // is rejecting it because the summary data isn't there. sql = string.Format("select fs.*, f.fileActivityDateTime from FileSummary fs join File f on f.idFile = fs.idFile where fs.idFile = {0}", _file); cmd.CommandText = sql; SQLiteDataReader rdr_summary = cmd.ExecuteReader(); if (rdr_summary.HasRows) { rdr_summary.Read(); SessionMesg sess = new SessionMesg(); //"fsMaxHeartRate" INTEGER,"fsMaxCadence" INTEGER,"fsMaxSpeed" FLOAT, "fsAvgPower" FLOAT, "fsMaxPower" FLOAT) sess.SetTotalElapsedTime((float)Convert.ToDouble(rdr_summary["fsDuration"])); sess.SetTotalMovingTime((float)Convert.ToDouble(rdr_summary["fsMovingTime"])); sess.SetTotalTimerTime((float)Convert.ToDouble(rdr_summary["fsMovingTime"])); sess.SetTotalDistance((float)(Convert.ToDouble(rdr_summary["fsDistance"]) * 1609.344)); // convert miles back to metres sess.SetTotalCalories(Convert.ToUInt16(rdr_summary["fsCalories"])); sess.SetAvgHeartRate(Convert.ToByte(Convert.ToInt32(rdr_summary["fsAvgHeart"]))); sess.SetAvgCadence(Convert.ToByte(Convert.ToInt32(rdr_summary["fsAvgCadence"]))); sess.SetAvgSpeed((float)(Convert.ToDouble(rdr_summary["fsAvgSpeed"]) / 2.23693629)); sess.SetTotalAscent(Convert.ToUInt16(Convert.ToDouble(rdr_summary["fsTotalAscent"]) / 3.2808399)); sess.SetTotalDescent(Convert.ToUInt16(Convert.ToDouble(rdr_summary["fsTotalDescent"]) / 3.2808399)); sess.SetMaxHeartRate(Convert.ToByte(Convert.ToInt32(rdr_summary["fsMaxHeartRate"]))); sess.SetMaxCadence(Convert.ToByte(Convert.ToInt32(rdr_summary["fsMaxCadence"]))); sess.SetMaxSpeed(Convert.ToByte(Convert.ToInt32(rdr_summary["fsMaxSpeed"]) / 2.23693629)); Dynastream.Fit.DateTime dt_start = new Dynastream.Fit.DateTime(Convert.ToDateTime(rdr_summary["fileActivityDateTime"])); sess.SetStartTime(dt_start); encode.Write(sess); } rdr_summary.Close(); // load and process the archived trackpoints for file sql = string.Format("select * from FileTrackpoints where idFile = {0}", _file); cmd.CommandText = sql; SQLiteDataReader rdr = cmd.ExecuteReader(); if (rdr.HasRows) { while (rdr.Read()) { // TODO: need to handle `0` lng/lat coordinates so that we're not mapped // as being in the middle of the atlantic ! :-) RecordMesg rec = new RecordMesg(); Dynastream.Fit.DateTime dt = new Dynastream.Fit.DateTime(System.DateTime.Parse((string)rdr["tpTime"])); rec.SetTimestamp(dt); rec.SetDistance((float)Convert.ToDouble(rdr["tpDistance"])); rec.SetHeartRate(Convert.ToByte(Convert.ToInt32(rdr["tpHeart"]))); rec.SetCadence(Convert.ToByte(Convert.ToInt32(rdr["tpCadence"]))); rec.SetTemperature(Convert.ToSByte(Convert.ToInt32(rdr["tpTemperature"]))); rec.SetAltitude((float)(Convert.ToDouble(rdr["tpAltitude"]) / 3.2808399)); // converted back to metres from ft in db rec.SetPositionLong((int)GeoMath.degrees_to_semicircle(Convert.ToDouble(rdr["tpLongitude"]))); rec.SetPositionLat((int)GeoMath.degrees_to_semicircle(Convert.ToDouble(rdr["tpLatitude"]))); rec.SetSpeed((float)Convert.ToDouble(rdr["tpSpeed"])); encode.Write(rec); } } encode.Close(); fitDest.Close(); MessageBox.Show("File Saved Successfully"); System.Diagnostics.Process.Start(saveFileDlg.FileName); } else { } }