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