peloton-to-garmin icon indicating copy to clipboard operation
peloton-to-garmin copied to clipboard

[Bug] Can't automatically upload TCX to Garmin

Open nick-stocks opened this issue 2 years ago • 3 comments

Describe the bug Unable to upload a TCX file to Garmin without first uploading a FIT file, as it appears FIT creates an upload directory. To Reproduce Steps to reproduce the behavior:

  1. Start the docker for the first time
  2. Set Garmin to upload using TCX file (as it appears to contain more detailed metrics)
  3. Trigger a sync
  4. Sync finishes v quickly with below log 2022-09-27 11:27:50.046 +01:00 [INF] No upload directory found. Nothing to do.

If you try to mount the upload directory at /app/working, you get the below error..

2022-09-27 11:36:40.483 +01:00 [ERR] Failed to clean up working directory: /app/working/upload
System.IO.IOException: Device or resource busy : '/app/working/upload'
   at System.IO.FileSystem.RemoveDirectoryInternal(DirectoryInfo directory, Boolean recursive, Boolean throwOnTopLevelDirectoryNotFound)
   at System.IO.FileSystem.RemoveDirectory(String fullPath, Boolean recursive)
   at System.IO.Directory.Delete(String path, Boolean recursive)
   at Common.IOWrapper.Cleanup(String dir) in /build/src/Common/FileHandling.cs:line 157
2022-09-27 11:36:40.495 +01:00 [ERR] Failed to clean up working directory: /app/working
System.IO.IOException: Directory not empty : '/app/working'
   at System.IO.FileSystem.RemoveDirectoryInternal(DirectoryInfo directory, Boolean recursive, Boolean throwOnTopLevelDirectoryNotFound)
   at System.IO.FileSystem.RemoveDirectory(String fullPath, Boolean recursive)
   at System.IO.Directory.Delete(String path, Boolean recursive)
   at Common.IOWrapper.Cleanup(String dir) in /build/src/Common/FileHandling.cs:line 157

Expected behavior Be able to upload a TCX file without having to upload a FIT file to create the upload directory. Logs

2022-09-27 11:26:38.705 +01:00 [INF] Sync Service stopped.
2022-09-27 11:27:07.623 +01:00 [INF] ["Fit"] Encoded file /app/working/4072b89f58fb4249bf1955ff5410653f_60_min_Power_Zone_Endurance_Ride_with_Matt_Wilpers.Fit
2022-09-27 11:27:07.629 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/4072b89f58fb4249bf1955ff5410653f_60_min_Power_Zone_Endurance_Ride_with_Matt_Wilpers.fit
2022-09-27 11:27:07.716 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/4072b89f58fb4249bf1955ff5410653f_60_min_Power_Zone_Endurance_Ride_with_Matt_Wilpers.tcx
2022-09-27 11:27:07.721 +01:00 [INF] ["Fit"] Encoded file /app/working/9617f9a492484f2da4a52cfd7e7b54b6_5_min_Post-Ride_Stretch_with_Ben_Alldis.Fit
2022-09-27 11:27:07.721 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/9617f9a492484f2da4a52cfd7e7b54b6_5_min_Post-Ride_Stretch_with_Ben_Alldis.fit
2022-09-27 11:27:07.725 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/9617f9a492484f2da4a52cfd7e7b54b6_5_min_Post-Ride_Stretch_with_Ben_Alldis.tcx
2022-09-27 11:27:07.777 +01:00 [INF] ["Fit"] Encoded file /app/working/55cdb5d6ef694ea6942169f774e6c2f8_30_min_80s_Rock_Ride_with_Ben_Alldis.Fit
2022-09-27 11:27:07.777 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/55cdb5d6ef694ea6942169f774e6c2f8_30_min_80s_Rock_Ride_with_Ben_Alldis.fit
2022-09-27 11:27:07.816 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/55cdb5d6ef694ea6942169f774e6c2f8_30_min_80s_Rock_Ride_with_Ben_Alldis.tcx
2022-09-27 11:27:07.837 +01:00 [INF] ["Fit"] Encoded file /app/working/ada381b2558646ef828d0cb17eaed606_23_min_Just_Walk-_Outdoor_with_JUST_WALK.Fit
2022-09-27 11:27:07.838 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/ada381b2558646ef828d0cb17eaed606_23_min_Just_Walk-_Outdoor_with_JUST_WALK.fit
2022-09-27 11:27:07.853 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/ada381b2558646ef828d0cb17eaed606_23_min_Just_Walk-_Outdoor_with_JUST_WALK.tcx
2022-09-27 11:27:07.862 +01:00 [INF] ["Fit"] Encoded file /app/working/72fe9627c8944b2f99590a684840483f_5_min_Cool_Down_Ride_with_Sam_Yo.Fit
2022-09-27 11:27:07.862 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/72fe9627c8944b2f99590a684840483f_5_min_Cool_Down_Ride_with_Sam_Yo.fit
2022-09-27 11:27:07.870 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/72fe9627c8944b2f99590a684840483f_5_min_Cool_Down_Ride_with_Sam_Yo.tcx
2022-09-27 11:27:07.891 +01:00 [INF] ["Fit"] Encoded file /app/working/265e4f1389c8462a92cbbaf0490457c1_20_min_Beginner_Ride_with_Hannah_Corbin.Fit
2022-09-27 11:27:07.891 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/265e4f1389c8462a92cbbaf0490457c1_20_min_Beginner_Ride_with_Hannah_Corbin.fit
2022-09-27 11:27:07.916 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/265e4f1389c8462a92cbbaf0490457c1_20_min_Beginner_Ride_with_Hannah_Corbin.tcx
2022-09-27 11:27:07.923 +01:00 [INF] ["Fit"] Encoded file /app/working/be5ac58aec1b4d5fae2e42117a524e52_5_min_Indie_Rock_Warm_Up_with_LANEBREAK.Fit
2022-09-27 11:27:07.924 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/be5ac58aec1b4d5fae2e42117a524e52_5_min_Indie_Rock_Warm_Up_with_LANEBREAK.fit
2022-09-27 11:27:07.930 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/be5ac58aec1b4d5fae2e42117a524e52_5_min_Indie_Rock_Warm_Up_with_LANEBREAK.tcx
2022-09-27 11:27:07.932 +01:00 [INF] No upload directory found. Nothing to do.
2022-09-27 11:27:49.726 +01:00 [INF] ["Fit"] Encoded file /app/working/9617f9a492484f2da4a52cfd7e7b54b6_5_min_Post-Ride_Stretch_with_Ben_Alldis.Fit
2022-09-27 11:27:49.727 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/9617f9a492484f2da4a52cfd7e7b54b6_5_min_Post-Ride_Stretch_with_Ben_Alldis.fit
2022-09-27 11:27:49.730 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/9617f9a492484f2da4a52cfd7e7b54b6_5_min_Post-Ride_Stretch_with_Ben_Alldis.tcx
2022-09-27 11:27:49.761 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/72fe9627c8944b2f99590a684840483f_5_min_Cool_Down_Ride_with_Sam_Yo.tcx
2022-09-27 11:27:49.816 +01:00 [INF] ["Fit"] Encoded file /app/working/72fe9627c8944b2f99590a684840483f_5_min_Cool_Down_Ride_with_Sam_Yo.Fit
2022-09-27 11:27:49.816 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/72fe9627c8944b2f99590a684840483f_5_min_Cool_Down_Ride_with_Sam_Yo.fit
2022-09-27 11:27:49.838 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/be5ac58aec1b4d5fae2e42117a524e52_5_min_Indie_Rock_Warm_Up_with_LANEBREAK.tcx
2022-09-27 11:27:49.838 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/ada381b2558646ef828d0cb17eaed606_23_min_Just_Walk-_Outdoor_with_JUST_WALK.tcx
2022-09-27 11:27:49.859 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/55cdb5d6ef694ea6942169f774e6c2f8_30_min_80s_Rock_Ride_with_Ben_Alldis.tcx
2022-09-27 11:27:49.875 +01:00 [INF] ["Fit"] Encoded file /app/working/be5ac58aec1b4d5fae2e42117a524e52_5_min_Indie_Rock_Warm_Up_with_LANEBREAK.Fit
2022-09-27 11:27:49.876 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/be5ac58aec1b4d5fae2e42117a524e52_5_min_Indie_Rock_Warm_Up_with_LANEBREAK.fit
2022-09-27 11:27:49.882 +01:00 [INF] ["Fit"] Encoded file /app/working/ada381b2558646ef828d0cb17eaed606_23_min_Just_Walk-_Outdoor_with_JUST_WALK.Fit
2022-09-27 11:27:49.883 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/ada381b2558646ef828d0cb17eaed606_23_min_Just_Walk-_Outdoor_with_JUST_WALK.fit
2022-09-27 11:27:49.915 +01:00 [INF] ["Fit"] Encoded file /app/working/265e4f1389c8462a92cbbaf0490457c1_20_min_Beginner_Ride_with_Hannah_Corbin.Fit
2022-09-27 11:27:49.916 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/265e4f1389c8462a92cbbaf0490457c1_20_min_Beginner_Ride_with_Hannah_Corbin.fit
2022-09-27 11:27:49.935 +01:00 [INF] ["Fit"] Encoded file /app/working/55cdb5d6ef694ea6942169f774e6c2f8_30_min_80s_Rock_Ride_with_Ben_Alldis.Fit
2022-09-27 11:27:49.937 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/55cdb5d6ef694ea6942169f774e6c2f8_30_min_80s_Rock_Ride_with_Ben_Alldis.fit
2022-09-27 11:27:49.938 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/265e4f1389c8462a92cbbaf0490457c1_20_min_Beginner_Ride_with_Hannah_Corbin.tcx
2022-09-27 11:27:49.969 +01:00 [INF] ["Tcx"] Backed up file /app/output/tcx/4072b89f58fb4249bf1955ff5410653f_60_min_Power_Zone_Endurance_Ride_with_Matt_Wilpers.tcx
2022-09-27 11:27:50.044 +01:00 [INF] ["Fit"] Encoded file /app/working/4072b89f58fb4249bf1955ff5410653f_60_min_Power_Zone_Endurance_Ride_with_Matt_Wilpers.Fit
2022-09-27 11:27:50.046 +01:00 [INF] ["Fit"] Backed up file /app/output/fit/4072b89f58fb4249bf1955ff5410653f_60_min_Power_Zone_Endurance_Ride_with_Matt_Wilpers.fit
2022-09-27 11:27:50.046 +01:00 [INF] No upload directory found. Nothing to do.

Installation (please complete the following information):

  • OS: linux (Portainer)
  • Method: Compose
  • Version: Stable image, root@home:/home/nick/docker/peloton-to-garmin# docker version Client: Docker Engine - Community Version: 20.10.17 API version: 1.41 Go version: go1.17.11 Git commit: 100c701 Built: Mon Jun 6 23:02:46 2022 OS/Arch: linux/amd64 Context: default Experimental: true

Server: Docker Engine - Community Engine: Version: 20.10.17 API version: 1.41 (minimum version 1.12) Go version: go1.17.11 Git commit: a89b842 Built: Mon Jun 6 23:00:51 2022 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.6.7 GitCommit: 0197261a30bf81f1ee8e6a4dd2dea0ef95d67ccb runc: Version: 1.1.3 GitCommit: v1.1.3-0-g6724737 docker-init: Version: 0.19.0 GitCommit: de40ad0 root@home:/home/nick/docker/peloton-to-garmin# docker-compose version docker-compose version 1.29.2, build 5becea4c docker-py version: 5.0.0 CPython version: 3.7.10 OpenSSL version: OpenSSL 1.1.0l 10 Sep 2019

nick-stocks avatar Sep 27 '22 10:09 nick-stocks

Set Garmin to upload using TCX file (as it appears to contain more detailed metrics)

So its actually the opposite. TCX contains far fewer metrics than FIT. FIT is the newer standard that Garmin is recommending going forward, it is regularly updated with the latest new data fields, and is the recommended upload type in P2G. I primarily keep TCX around because it is a human readable format which can be handy for personal backup purposes.

If you try to mount the upload directory at /app/working, you get the below error..

This is because the app/working directory should not be mounted it is transient.

Be able to upload a TCX file without having to upload a FIT file to create the upload directory.

Will look into why the TCX file is not getting uploaded. While its not recommended (in favor of FIT), its still fair to expect that it would work.

philosowaffle avatar Sep 27 '22 12:09 philosowaffle

@philosowaffle Thanks - I was finding TCX was uploading my output and power zones correctly, while using FIT seemed to create activities with very limited details and generically named "Cycling". I was also getting errors with Garmin responses saying 'Fit not supported'. After moving to the latest docker instead of stable, those particular problems have gone away for whatever reason, so FIT is giving me all the data now and working fine. So while this is an issue, it's not now an issue I'm impacted by.

nick-stocks avatar Sep 27 '22 12:09 nick-stocks

while using FIT seemed to create activities with very limited details and generically named "Cycling".

Do you mind sharing some example configurations you tried? I feel like something is backwards either in the P2G documentation, the code, or in the config itself. The behavior you're describing is exactly how TCX behaves, not FIT.

I was also getting errors with Garmin responses saying 'Fit not supported'.

When uploading to Garmin, P2G has to tell Garmin what the type is of the file. This error indicates a case where P2G may have been trying to upload a FIT file while telling Garmin it was type=tcx. Something I can also look into further.

This will all just help me narrow down the core of the problem, and do effective testing to make sure it truly is resolved on latest.

philosowaffle avatar Sep 27 '22 13:09 philosowaffle

I suspect this issue is the same as #361

philosowaffle avatar Nov 10 '22 00:11 philosowaffle