fit-file-faker 1.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fit-file-faker might be problematic. Click here for more details.

@@ -0,0 +1,7 @@
1
+ Copyright 2024, Joshua Taillon
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,305 @@
1
+ Metadata-Version: 2.1
2
+ Name: fit-file-faker
3
+ Version: 1.2.0
4
+ Summary: A small tool to edit and upload FIT files to Garmin Connect
5
+ Author-email: Josh Taillon <jat255@gmail.com>
6
+ Project-URL: Homepage, https://github.com/jat255/Fit-File-Faker
7
+ Project-URL: Issues, https://github.com/jat255/Fit-File-Faker/issues
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.12.0
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE.md
14
+ Requires-Dist: fit-tool>=0.9.13
15
+ Requires-Dist: garth>=0.5.2
16
+ Requires-Dist: platformdirs>=4.3.6
17
+ Requires-Dist: questionary>=2.1.0
18
+ Requires-Dist: rich>=13.9.4
19
+ Requires-Dist: semver>=3.0.2
20
+ Requires-Dist: watchdog>=6.0.0
21
+
22
+ # Fit File Faker - a FIT File editor and uploader
23
+
24
+ This repo contains a tool that will edit [FIT](https://developer.garmin.com/fit/overview/) files
25
+ to make them appear to come from a Garmin device (Edge 830, currently) and upload them to Garmin Connect
26
+ using the [`garth`](https://github.com/matin/garth/) library. The FIT editing
27
+ is done using Stages Cycling's [`fit_tool`](https://bitbucket.org/stagescycling/python_fit_tool/src/main/) library.
28
+
29
+ The primary use case for this is that [TrainingPeaks Virtual](https://www.trainingpeaks.com/virtual/) (previously
30
+ [indieVelo](https://indievelo.com/)) does not support (AFAIK, Garmin does not allow) automatic uploading to
31
+ [Garmin Connect](http://connect.garmin.com/). The files can be manually uploaded after the fact,
32
+ but since they are not "from Garmin", they will not be used to calculate Garmin's "Training Effect",
33
+ which is used for suggested workouts and other stuff. By changing the FIT file to appear to come
34
+ from a Garmin device, those features should be enabled.
35
+
36
+ Other users have reported using this tool to edit FIT files produced by [Zwift](https://www.zwift.com/)
37
+ prior to uploading to Garmin Connect so that activities on that platform will count towards Garmin Connect
38
+ badges and challenges (see [1](https://forums.zwift.com/t/garmin-disabled-zwift-rides-badges/528612) and
39
+ [2](https://forums.garmin.com/apps-software/mobile-apps-web/f/garmin-connect-web/251574/zwift-rides-no-longer-count-towards-challenges)).
40
+
41
+ ## Contributors
42
+
43
+ - [jat255](https://github.com/jat255): Primary author
44
+ - [benjmarshall](https://github.com/benjmarshall): bug fixes, monitor mode, and other improvements
45
+ - [Kellett](https://github.com/Kellett): support for Zwift FIT files
46
+
47
+ ## Installation
48
+
49
+ Requires Python 3.12. If your system python is older than that,
50
+ [pyenv](https://github.com/pyenv/pyenv) or [uv](https://docs.astral.sh/uv/) can be
51
+ used to manage locally installed versions.
52
+
53
+ This tool should work cross-platform on Windows, MacOS, or Linux, though it is primarily
54
+ developed on Linux, so it's possible there are some cross-platform bugs.
55
+
56
+ ### pipx install
57
+
58
+ If you have [pipx](https://pipx.pypa.io/latest/installation/) installed, a simple
59
+
60
+ ```bash
61
+ $ pipx install fit-file-faker
62
+ ```
63
+
64
+ will install the tool, and make the script named `fit-file-faker` available on your PATH.
65
+
66
+ ### Manual virtual environment
67
+
68
+ You can also install manually using `pip`. If so, it's best to create a new
69
+ virtual environment:
70
+
71
+ ```bash
72
+ $ python -m venv .venv
73
+ $ source .venv/bin/activate
74
+ ```
75
+
76
+ Then install via pip:
77
+
78
+ ```bash
79
+ $ pip install fit-file-faker
80
+ ```
81
+
82
+ The pip package installs a script named `fit-file-faker` that should be available on your
83
+ path assuming the virtual envrionment is activated.
84
+
85
+ ### Development install
86
+
87
+ If you want to install a development version, clone the repo, and use the
88
+ [uv](https://docs.astral.sh/uv/):
89
+
90
+ ```bash
91
+ $ git clone https://github.com/jat255/fit_file_uploader.git
92
+ $ cd fit_file_uploader
93
+ $ uv sync # this installs the dependencies
94
+ ```
95
+
96
+ ## Configuration
97
+
98
+ The script uses a configuration file named `.config.json` stored in your system's user config directory
99
+ (as determined by the [`platformdirs`](https://github.com/tox-dev/platformdirs) library).
100
+ An example is provided in this repo in `.config.json.example`:
101
+
102
+ ```json
103
+ {
104
+ "garmin_username": "username",
105
+ "garmin_password": "password",
106
+ "fitfiles_path": "C:\\Users\\username\\Documents\\TPVirtual\\0123456789ABCDEF\\FITFiles"
107
+ }
108
+ ```
109
+
110
+ The best way to fill out this config file is to run the "initial setup"
111
+ option via the `-s` flag, which will allow you to define the three required values interactively:
112
+
113
+ ```bash
114
+ $ fit-file-faker -s
115
+
116
+ [13:50:02] WARNING Required value "garmin_username" not found in config app.py:404
117
+ ? Enter value to use for "garmin_username" username
118
+ [13:50:05] WARNING Required value "garmin_password" not found in config app.py:404
119
+ ? Enter value to use for "garmin_password" ********
120
+ [13:50:06] WARNING Required value "fitfiles_path" not found in config app.py:404
121
+ INFO Getting FITFiles folder app.py:133
122
+ WARNING TrainingPeaks Virtual user folder can only be automatically app.py:175
123
+ detected on Windows and OSX
124
+ ? Please enter your TrainingPeaks Virtual data folder (by default, ends with "TPVirtual"):
125
+ /home/user/Documents/TPVirtual
126
+ ? Found TP Virtual User directory at "/home/user/Documents/TPVirtual/0123456789ABCDEF", is this correct?
127
+ yes
128
+ [13:50:17] INFO Found TP Virtual User directory: "/home/user/Documents/TPVirtual app.py:158
129
+ sync/0123456789ABCEDF", setting "fitfiles_path" in config file
130
+ INFO Config file is now: app.py:440
131
+ {
132
+ "garmin_username": "username",
133
+ "garmin_password": "<**hidden**>",
134
+ "fitfiles_path": "/home/user/Documents/TPVirtual/0123456789ABCDEF/FITFiles"
135
+ }
136
+ INFO Config file has been written, now run one of the other options app.py:530
137
+ to start editing/uploading files!
138
+ ```
139
+
140
+ ## Usage
141
+
142
+ The script has a few options. To see the help, run with the `-h` flag:
143
+
144
+ ```bash
145
+ $ fit-file-faker -h
146
+ ```
147
+ ```
148
+ usage: fit-file-faker [-h] [-s] [-u] [-ua] [-p] [-m] [--dryrun] [-v] [input_path]
149
+
150
+ Tool to add Garmin device information to FIT files and upload them to Garmin Connect. Currently,
151
+ only FIT files produced by TrainingPeaks Virtual (https://www.trainingpeaks.com/virtual/) and
152
+ Zwift (https://www.zwift.com/) are supported, but it's possible others may work.
153
+
154
+
155
+ positional arguments:
156
+ input_path the FIT file or directory to process. This argument can be omitted if
157
+ the 'fitfiles_path' config value is set (that directory will be used
158
+ instead). By default, files will just be edited. Specify the "-u" flag
159
+ to also upload them to Garmin Connect.
160
+
161
+ options:
162
+ -h, --help show this help message and exit
163
+ -s, --initial-setup Use this option to interactively initialize the configuration file
164
+ (.config.json)
165
+ -u, --upload upload FIT file (after editing) to Garmin Connect
166
+ -ua, --upload-all upload all FIT files in directory (if they are not in "already
167
+ processed" list)
168
+ -p, --preinitialize preinitialize the list of processed FIT files (mark all existing files
169
+ in directory as already uploaded)
170
+ -m, --monitor monitor a directory and upload all newly created FIT files as they are
171
+ found
172
+ -d, --dryrun perform a dry run, meaning any files processed will not be saved nor
173
+ uploaded
174
+ -v, --verbose increase verbosity of log output
175
+ ```
176
+
177
+ ### Basic usage
178
+
179
+ The default behavior with no other options load a given FIT file, and output a file named `path_to_file_modified.fit`
180
+ that has been edited, and can be manually imported to Garmin Connect:
181
+
182
+ ```bash
183
+ $ fit-file-faker path_to_file.fit
184
+ ```
185
+
186
+ If a directory is supplied rather than a single file, all FIT files in that directory will be processed in
187
+ the same way.
188
+
189
+ Supplying the `-u` option will attempt to upload the edited file to Garmin Connect. If
190
+ your credentials are not stored in the configuration file, the script will prompt you for them.
191
+ The OAuth credentials obtained for the Garmin web service will be stored in a directory
192
+ named `.garth` in your system's user cache folder (as determined by
193
+ [`platformdirs`](https://github.com/tox-dev/platformdirs)). See the `garth` library's
194
+ [documentation](https://github.com/matin/garth/?tab=readme-ov-file#authentication-and-stability)
195
+ for details:
196
+
197
+ ```bash
198
+ $ fit-file-faker -u path_to_file.fit
199
+ ```
200
+ ```
201
+ [12:14:06] INFO Activity timestamp is "2024-05-21T17:15:48" app.py:84
202
+ INFO Saving modified data to path_to_file_modified.fit app.py:106
203
+ [12:14:08] INFO ✅ Successfully uploaded "path_to_file.fit" app.py:137
204
+ ```
205
+
206
+ The `-v` flag can be used (with any of the other options) to provide more debugging output:
207
+
208
+ ```bash
209
+ $ fit-file-faker -u path_to_file.fit -v
210
+ ```
211
+ ```
212
+ [12:38:33] INFO Activity timestamp is "2024-05-21T17:15:48" app.py:84
213
+ DEBUG Record: 1 - manufacturer: 255 ("DEVELOPMENT") - product: 0 - garmin app.py:55
214
+ product: None ("BLANK")
215
+ DEBUG Modifying values app.py:87
216
+ DEBUG New Record: 1 - manufacturer: 1 ("GARMIN") - product: 3122 - garmin app.py:55
217
+ product: 3122 ("GarminProduct.EDGE_830")
218
+ DEBUG Record: 14 - manufacturer: 32 ("WAHOO_FITNESS") - product: 40 - garmin app.py:55
219
+ product: None ("BLANK")
220
+ DEBUG Modifying values app.py:97
221
+ DEBUG New Record: 14 - manufacturer: 1 ("GARMIN") - product: 3122 - garmin app.py:55
222
+ product: 3122 ("GarminProduct.EDGE_830")
223
+ DEBUG Record: 15 - manufacturer: 32 ("WAHOO_FITNESS") - product: 6 - garmin app.py:55
224
+ product: None ("BLANK")
225
+ DEBUG Modifying values app.py:97
226
+ DEBUG New Record: 15 - manufacturer: 1 ("GARMIN") - product: 3122 - garmin app.py:55
227
+ product: 3122 ("GarminProduct.EDGE_830")
228
+ DEBUG Record: 16 - manufacturer: 1 ("GARMIN") - product: 18 - garmin product: app.py:55
229
+ 18 ("BLANK")
230
+ INFO Saving modified data to app.py:106
231
+ "path_to_file_modified.fit"
232
+ [12:38:34] DEBUG Using stored Garmin credentials from ".garth" directory app.py:118
233
+ [12:38:35] INFO ✅ Successfully uploaded "path_to_file.fit" app.py:137
234
+ ```
235
+
236
+ ### "Upload all" and "monitor" modes
237
+
238
+ The `--upload-all` option will search for all FIT files eith in the directory given on the command line,
239
+ or in the one specified in the `fitfiles_path` config option. The script will compare the files found to a
240
+ list of files already seen (stored in that directory's `.uploaded_files.json` file), edit them, and upload
241
+ each to Garmin Connect. The edited files will be written into a temporary file and discarded when the
242
+ script finishes running, and the filenames will be stored into a JSON file in the current directory so
243
+ they are skipped the next time the script is run.
244
+
245
+ The upload all function can alternatively be automated using the `--monitor` option, which will start
246
+ watching the filesystem in the specified directory for any new FIT files, and continue running until
247
+ the user interrupts the process by pressing `ctrl-c`. Here is an example output when a new file named
248
+ `new_fit_file.fit` is detected:
249
+
250
+ ```
251
+ $ fit-file-faker --monitor /home/user/Documents/TPVirtual/0123456789ABCEDF/FITFiles
252
+
253
+ [14:03:32] INFO Using path "/home/user/Documents/TPVirtual/ app.py:561
254
+ 0123456789ABCEDF/FITFiles" from command line input
255
+ INFO Monitoring directory: "/home/user/Documents/TPVirtual/ app.py:367
256
+ 0123456789ABCEDF/FITFiles"
257
+ [14:03:44] INFO New file detected - "/home/user/Documents/TPVirtual/ app.py:94
258
+ 0123456789ABCEDF/FITFiles/new_fit_file.fit"; sleeping for
259
+ 5 seconds to ensure TPV finishes writing file
260
+ [14:03:50] INFO Found 1 files to edit/upload app.py:333
261
+ INFO Processing "new_fit_file.fit" app.py:340
262
+ INFO Processing "/home/user/Documents/TPVirtual app.py:202
263
+ sync/0123456789ABCEDF/FITFiles/new_fit_file.fit"
264
+ [14:03:58] INFO Activity timestamp is "2025-01-03T17:01:45" app.py:223
265
+ [14:03:59] INFO Saving modified data to "/tmp/tmpsn4gvpkh" app.py:250
266
+ [14:04:00] INFO Uploading modified file to Garmin Connect app.py:346
267
+ [14:04:01] INFO Uploading "/tmp/tmpsn4gvpkh" using garth app.py:295
268
+ ^C[14:04:46] INFO Received keyboard interrupt, shutting down monitor app.py:372
269
+ ```
270
+
271
+ If your TrainingPeaks Virtual user data folder already contains FIT files which you have previously uploaded
272
+ to Garmin Connect using a different method then you can pre-initialise the list of uploaded files to avoid
273
+ any possibility of uploading duplicates (though these files *should* be rejected by Garmin Connect
274
+ if they're exact duplicates). Use the `--preinitialize` option to process a directory (defaults to
275
+ the configured TrainingPeaks Virtual user data directory) and add all files to the list of previous uploaded
276
+ files. After this any use of the `--upload-all` or `--monitor` options will ignore these pre-existing files.
277
+
278
+ ### Already uploaded files
279
+
280
+ A note: if a file with the same timestamp already exists on the Garmin Connect account, Garmin
281
+ will reject the upload. This script will detect that, and output something like the following:
282
+
283
+ ```bash
284
+ $ fit-file-faker -u path_to_file.fit -v
285
+ ```
286
+ ```
287
+ [13:32:48] INFO Activity timestamp is "2024-05-10T17:17:34" app.py:85
288
+ INFO Saving modified data to "path_to_file_modified.fit" app.py:107
289
+ [13:32:49] WARNING ❌ Received HTTP conflict (activity already exists) for app.py:143
290
+ "path_to_file.fit"
291
+ ```
292
+
293
+ ## Troubleshooting
294
+
295
+ If you run into problems, please
296
+ [create an issue](https://github.com/jat255/fit_file_uploader/issues/new/choose) on the GitHub
297
+ repo. As this is a side-project provided for free (as in speech and beer), support times may vary 😅.
298
+
299
+ ## Disclaimer
300
+
301
+ The use of any registered or unregistered trademarks owned by third-parties are used only for
302
+ informational purposes and no endorsement of this software by the owners of such trademarks are
303
+ implied, explicitly or otherwise. The terms/trademarks indieVelo, TrainingPeaks, TrainingPeaks Virtual,
304
+ Garmin Connect, Stages Cycling, and any others are used under fair use doctrine solely to
305
+ facilitate understanding.
@@ -0,0 +1,284 @@
1
+ # Fit File Faker - a FIT File editor and uploader
2
+
3
+ This repo contains a tool that will edit [FIT](https://developer.garmin.com/fit/overview/) files
4
+ to make them appear to come from a Garmin device (Edge 830, currently) and upload them to Garmin Connect
5
+ using the [`garth`](https://github.com/matin/garth/) library. The FIT editing
6
+ is done using Stages Cycling's [`fit_tool`](https://bitbucket.org/stagescycling/python_fit_tool/src/main/) library.
7
+
8
+ The primary use case for this is that [TrainingPeaks Virtual](https://www.trainingpeaks.com/virtual/) (previously
9
+ [indieVelo](https://indievelo.com/)) does not support (AFAIK, Garmin does not allow) automatic uploading to
10
+ [Garmin Connect](http://connect.garmin.com/). The files can be manually uploaded after the fact,
11
+ but since they are not "from Garmin", they will not be used to calculate Garmin's "Training Effect",
12
+ which is used for suggested workouts and other stuff. By changing the FIT file to appear to come
13
+ from a Garmin device, those features should be enabled.
14
+
15
+ Other users have reported using this tool to edit FIT files produced by [Zwift](https://www.zwift.com/)
16
+ prior to uploading to Garmin Connect so that activities on that platform will count towards Garmin Connect
17
+ badges and challenges (see [1](https://forums.zwift.com/t/garmin-disabled-zwift-rides-badges/528612) and
18
+ [2](https://forums.garmin.com/apps-software/mobile-apps-web/f/garmin-connect-web/251574/zwift-rides-no-longer-count-towards-challenges)).
19
+
20
+ ## Contributors
21
+
22
+ - [jat255](https://github.com/jat255): Primary author
23
+ - [benjmarshall](https://github.com/benjmarshall): bug fixes, monitor mode, and other improvements
24
+ - [Kellett](https://github.com/Kellett): support for Zwift FIT files
25
+
26
+ ## Installation
27
+
28
+ Requires Python 3.12. If your system python is older than that,
29
+ [pyenv](https://github.com/pyenv/pyenv) or [uv](https://docs.astral.sh/uv/) can be
30
+ used to manage locally installed versions.
31
+
32
+ This tool should work cross-platform on Windows, MacOS, or Linux, though it is primarily
33
+ developed on Linux, so it's possible there are some cross-platform bugs.
34
+
35
+ ### pipx install
36
+
37
+ If you have [pipx](https://pipx.pypa.io/latest/installation/) installed, a simple
38
+
39
+ ```bash
40
+ $ pipx install fit-file-faker
41
+ ```
42
+
43
+ will install the tool, and make the script named `fit-file-faker` available on your PATH.
44
+
45
+ ### Manual virtual environment
46
+
47
+ You can also install manually using `pip`. If so, it's best to create a new
48
+ virtual environment:
49
+
50
+ ```bash
51
+ $ python -m venv .venv
52
+ $ source .venv/bin/activate
53
+ ```
54
+
55
+ Then install via pip:
56
+
57
+ ```bash
58
+ $ pip install fit-file-faker
59
+ ```
60
+
61
+ The pip package installs a script named `fit-file-faker` that should be available on your
62
+ path assuming the virtual envrionment is activated.
63
+
64
+ ### Development install
65
+
66
+ If you want to install a development version, clone the repo, and use the
67
+ [uv](https://docs.astral.sh/uv/):
68
+
69
+ ```bash
70
+ $ git clone https://github.com/jat255/fit_file_uploader.git
71
+ $ cd fit_file_uploader
72
+ $ uv sync # this installs the dependencies
73
+ ```
74
+
75
+ ## Configuration
76
+
77
+ The script uses a configuration file named `.config.json` stored in your system's user config directory
78
+ (as determined by the [`platformdirs`](https://github.com/tox-dev/platformdirs) library).
79
+ An example is provided in this repo in `.config.json.example`:
80
+
81
+ ```json
82
+ {
83
+ "garmin_username": "username",
84
+ "garmin_password": "password",
85
+ "fitfiles_path": "C:\\Users\\username\\Documents\\TPVirtual\\0123456789ABCDEF\\FITFiles"
86
+ }
87
+ ```
88
+
89
+ The best way to fill out this config file is to run the "initial setup"
90
+ option via the `-s` flag, which will allow you to define the three required values interactively:
91
+
92
+ ```bash
93
+ $ fit-file-faker -s
94
+
95
+ [13:50:02] WARNING Required value "garmin_username" not found in config app.py:404
96
+ ? Enter value to use for "garmin_username" username
97
+ [13:50:05] WARNING Required value "garmin_password" not found in config app.py:404
98
+ ? Enter value to use for "garmin_password" ********
99
+ [13:50:06] WARNING Required value "fitfiles_path" not found in config app.py:404
100
+ INFO Getting FITFiles folder app.py:133
101
+ WARNING TrainingPeaks Virtual user folder can only be automatically app.py:175
102
+ detected on Windows and OSX
103
+ ? Please enter your TrainingPeaks Virtual data folder (by default, ends with "TPVirtual"):
104
+ /home/user/Documents/TPVirtual
105
+ ? Found TP Virtual User directory at "/home/user/Documents/TPVirtual/0123456789ABCDEF", is this correct?
106
+ yes
107
+ [13:50:17] INFO Found TP Virtual User directory: "/home/user/Documents/TPVirtual app.py:158
108
+ sync/0123456789ABCEDF", setting "fitfiles_path" in config file
109
+ INFO Config file is now: app.py:440
110
+ {
111
+ "garmin_username": "username",
112
+ "garmin_password": "<**hidden**>",
113
+ "fitfiles_path": "/home/user/Documents/TPVirtual/0123456789ABCDEF/FITFiles"
114
+ }
115
+ INFO Config file has been written, now run one of the other options app.py:530
116
+ to start editing/uploading files!
117
+ ```
118
+
119
+ ## Usage
120
+
121
+ The script has a few options. To see the help, run with the `-h` flag:
122
+
123
+ ```bash
124
+ $ fit-file-faker -h
125
+ ```
126
+ ```
127
+ usage: fit-file-faker [-h] [-s] [-u] [-ua] [-p] [-m] [--dryrun] [-v] [input_path]
128
+
129
+ Tool to add Garmin device information to FIT files and upload them to Garmin Connect. Currently,
130
+ only FIT files produced by TrainingPeaks Virtual (https://www.trainingpeaks.com/virtual/) and
131
+ Zwift (https://www.zwift.com/) are supported, but it's possible others may work.
132
+
133
+
134
+ positional arguments:
135
+ input_path the FIT file or directory to process. This argument can be omitted if
136
+ the 'fitfiles_path' config value is set (that directory will be used
137
+ instead). By default, files will just be edited. Specify the "-u" flag
138
+ to also upload them to Garmin Connect.
139
+
140
+ options:
141
+ -h, --help show this help message and exit
142
+ -s, --initial-setup Use this option to interactively initialize the configuration file
143
+ (.config.json)
144
+ -u, --upload upload FIT file (after editing) to Garmin Connect
145
+ -ua, --upload-all upload all FIT files in directory (if they are not in "already
146
+ processed" list)
147
+ -p, --preinitialize preinitialize the list of processed FIT files (mark all existing files
148
+ in directory as already uploaded)
149
+ -m, --monitor monitor a directory and upload all newly created FIT files as they are
150
+ found
151
+ -d, --dryrun perform a dry run, meaning any files processed will not be saved nor
152
+ uploaded
153
+ -v, --verbose increase verbosity of log output
154
+ ```
155
+
156
+ ### Basic usage
157
+
158
+ The default behavior with no other options load a given FIT file, and output a file named `path_to_file_modified.fit`
159
+ that has been edited, and can be manually imported to Garmin Connect:
160
+
161
+ ```bash
162
+ $ fit-file-faker path_to_file.fit
163
+ ```
164
+
165
+ If a directory is supplied rather than a single file, all FIT files in that directory will be processed in
166
+ the same way.
167
+
168
+ Supplying the `-u` option will attempt to upload the edited file to Garmin Connect. If
169
+ your credentials are not stored in the configuration file, the script will prompt you for them.
170
+ The OAuth credentials obtained for the Garmin web service will be stored in a directory
171
+ named `.garth` in your system's user cache folder (as determined by
172
+ [`platformdirs`](https://github.com/tox-dev/platformdirs)). See the `garth` library's
173
+ [documentation](https://github.com/matin/garth/?tab=readme-ov-file#authentication-and-stability)
174
+ for details:
175
+
176
+ ```bash
177
+ $ fit-file-faker -u path_to_file.fit
178
+ ```
179
+ ```
180
+ [12:14:06] INFO Activity timestamp is "2024-05-21T17:15:48" app.py:84
181
+ INFO Saving modified data to path_to_file_modified.fit app.py:106
182
+ [12:14:08] INFO ✅ Successfully uploaded "path_to_file.fit" app.py:137
183
+ ```
184
+
185
+ The `-v` flag can be used (with any of the other options) to provide more debugging output:
186
+
187
+ ```bash
188
+ $ fit-file-faker -u path_to_file.fit -v
189
+ ```
190
+ ```
191
+ [12:38:33] INFO Activity timestamp is "2024-05-21T17:15:48" app.py:84
192
+ DEBUG Record: 1 - manufacturer: 255 ("DEVELOPMENT") - product: 0 - garmin app.py:55
193
+ product: None ("BLANK")
194
+ DEBUG Modifying values app.py:87
195
+ DEBUG New Record: 1 - manufacturer: 1 ("GARMIN") - product: 3122 - garmin app.py:55
196
+ product: 3122 ("GarminProduct.EDGE_830")
197
+ DEBUG Record: 14 - manufacturer: 32 ("WAHOO_FITNESS") - product: 40 - garmin app.py:55
198
+ product: None ("BLANK")
199
+ DEBUG Modifying values app.py:97
200
+ DEBUG New Record: 14 - manufacturer: 1 ("GARMIN") - product: 3122 - garmin app.py:55
201
+ product: 3122 ("GarminProduct.EDGE_830")
202
+ DEBUG Record: 15 - manufacturer: 32 ("WAHOO_FITNESS") - product: 6 - garmin app.py:55
203
+ product: None ("BLANK")
204
+ DEBUG Modifying values app.py:97
205
+ DEBUG New Record: 15 - manufacturer: 1 ("GARMIN") - product: 3122 - garmin app.py:55
206
+ product: 3122 ("GarminProduct.EDGE_830")
207
+ DEBUG Record: 16 - manufacturer: 1 ("GARMIN") - product: 18 - garmin product: app.py:55
208
+ 18 ("BLANK")
209
+ INFO Saving modified data to app.py:106
210
+ "path_to_file_modified.fit"
211
+ [12:38:34] DEBUG Using stored Garmin credentials from ".garth" directory app.py:118
212
+ [12:38:35] INFO ✅ Successfully uploaded "path_to_file.fit" app.py:137
213
+ ```
214
+
215
+ ### "Upload all" and "monitor" modes
216
+
217
+ The `--upload-all` option will search for all FIT files eith in the directory given on the command line,
218
+ or in the one specified in the `fitfiles_path` config option. The script will compare the files found to a
219
+ list of files already seen (stored in that directory's `.uploaded_files.json` file), edit them, and upload
220
+ each to Garmin Connect. The edited files will be written into a temporary file and discarded when the
221
+ script finishes running, and the filenames will be stored into a JSON file in the current directory so
222
+ they are skipped the next time the script is run.
223
+
224
+ The upload all function can alternatively be automated using the `--monitor` option, which will start
225
+ watching the filesystem in the specified directory for any new FIT files, and continue running until
226
+ the user interrupts the process by pressing `ctrl-c`. Here is an example output when a new file named
227
+ `new_fit_file.fit` is detected:
228
+
229
+ ```
230
+ $ fit-file-faker --monitor /home/user/Documents/TPVirtual/0123456789ABCEDF/FITFiles
231
+
232
+ [14:03:32] INFO Using path "/home/user/Documents/TPVirtual/ app.py:561
233
+ 0123456789ABCEDF/FITFiles" from command line input
234
+ INFO Monitoring directory: "/home/user/Documents/TPVirtual/ app.py:367
235
+ 0123456789ABCEDF/FITFiles"
236
+ [14:03:44] INFO New file detected - "/home/user/Documents/TPVirtual/ app.py:94
237
+ 0123456789ABCEDF/FITFiles/new_fit_file.fit"; sleeping for
238
+ 5 seconds to ensure TPV finishes writing file
239
+ [14:03:50] INFO Found 1 files to edit/upload app.py:333
240
+ INFO Processing "new_fit_file.fit" app.py:340
241
+ INFO Processing "/home/user/Documents/TPVirtual app.py:202
242
+ sync/0123456789ABCEDF/FITFiles/new_fit_file.fit"
243
+ [14:03:58] INFO Activity timestamp is "2025-01-03T17:01:45" app.py:223
244
+ [14:03:59] INFO Saving modified data to "/tmp/tmpsn4gvpkh" app.py:250
245
+ [14:04:00] INFO Uploading modified file to Garmin Connect app.py:346
246
+ [14:04:01] INFO Uploading "/tmp/tmpsn4gvpkh" using garth app.py:295
247
+ ^C[14:04:46] INFO Received keyboard interrupt, shutting down monitor app.py:372
248
+ ```
249
+
250
+ If your TrainingPeaks Virtual user data folder already contains FIT files which you have previously uploaded
251
+ to Garmin Connect using a different method then you can pre-initialise the list of uploaded files to avoid
252
+ any possibility of uploading duplicates (though these files *should* be rejected by Garmin Connect
253
+ if they're exact duplicates). Use the `--preinitialize` option to process a directory (defaults to
254
+ the configured TrainingPeaks Virtual user data directory) and add all files to the list of previous uploaded
255
+ files. After this any use of the `--upload-all` or `--monitor` options will ignore these pre-existing files.
256
+
257
+ ### Already uploaded files
258
+
259
+ A note: if a file with the same timestamp already exists on the Garmin Connect account, Garmin
260
+ will reject the upload. This script will detect that, and output something like the following:
261
+
262
+ ```bash
263
+ $ fit-file-faker -u path_to_file.fit -v
264
+ ```
265
+ ```
266
+ [13:32:48] INFO Activity timestamp is "2024-05-10T17:17:34" app.py:85
267
+ INFO Saving modified data to "path_to_file_modified.fit" app.py:107
268
+ [13:32:49] WARNING ❌ Received HTTP conflict (activity already exists) for app.py:143
269
+ "path_to_file.fit"
270
+ ```
271
+
272
+ ## Troubleshooting
273
+
274
+ If you run into problems, please
275
+ [create an issue](https://github.com/jat255/fit_file_uploader/issues/new/choose) on the GitHub
276
+ repo. As this is a side-project provided for free (as in speech and beer), support times may vary 😅.
277
+
278
+ ## Disclaimer
279
+
280
+ The use of any registered or unregistered trademarks owned by third-parties are used only for
281
+ informational purposes and no endorsement of this software by the owners of such trademarks are
282
+ implied, explicitly or otherwise. The terms/trademarks indieVelo, TrainingPeaks, TrainingPeaks Virtual,
283
+ Garmin Connect, Stages Cycling, and any others are used under fair use doctrine solely to
284
+ facilitate understanding.