Json Config File
Based on your installation method, configuration may be provided via a configuration.local.json
or it may be done via the user interface. In the below documentation you will see the information for both the JSON config file, and the Web UI.
By default, P2G looks for a file named configuration.local.json
in the same directory where the program is run.
The config file is written in JSON and supports hot-reload for all fields except the following:
App.PollingintervalSeconds
Observability
Section
The config file is organized into the below sections.
Section | Platforms | Description |
---|---|---|
Api Config | Web UI | This section provides global settings for the P2G Api. |
WebUI Config | Web UI | This section provides global settings for the P2G Web UI. |
App Config | Headless | This section provides global settings for the P2G application. |
Format Config | Headless | This section provides settings related to conversions and what formats should be created/saved. |
Peloton Config | Headless | This section provides settings related to fetching workouts from Peloton. |
Garmin Config | Headless | This section provides settings related to uploading workouts to Garmin. |
Observability Config | All | This section provides settings related to Metrics, Logs, and Traces for monitoring purposes. |
Api Config
If you aren't running the Web UI version of P2G you can ignore this section.
This section lives in webui.local.json
.
"Api": {
"HostUrl": "http://p2g-api:8080"
}
Field | Required | Default | UI Setting Location | Description |
---|---|---|---|---|
HostUrl | yes | null |
none | The host and port for the Web UI to communicate with the Api. |
Advanced usage
Typically this section is only needed in the webui.local.json
so that the Web UI knows where to find the running Api. However, if you have a unique setup and need to modify the Host and Port the Api binds to, then you can also provide this config section in the api.local.json
.
"Api": {
"HostUrl": "http://*:8080"
}
Field | Required | Default | UI Setting Location | Description |
---|---|---|---|---|
HostUrl | no | http://localhost:8080 |
none | The host and port the Api should bind to and listen on. |
WebUI Config
If you aren't running the Web UI version of P2G you can ignore this section.
You can provide this config section in the webui.local.json
.
"WebUI": {
"HostUrl": "http://*:8080"
}
Field | Required | Default | UI Setting Location | Description |
---|---|---|---|---|
HostUrl | no | http://localhost:8080 |
none | The host and port the WebUI should bind to and listen on. |
App Config
This section provides global settings for the P2G application.
"App": {
"EnablePolling": true,
"PollingIntervalSeconds": 86400,
"CheckForUpdates": true
}
Field | Required | Default | UI Setting Location | Description |
---|---|---|---|---|
EnablePolling | no | true |
App Tab |
true if you wish P2G to run continuously and poll Peloton for new workouts. |
PollingIntervalSeconds | no | 86400 | App Tab |
The polling interval in seconds determines how frequently P2G should check for new workouts. Be warned, that setting this to a frequency of hourly or less may get you flagged by Peloton as a bad actor and they may reset your password. The default is set to Daily. |
CheckForUpdates | no | true |
App Tab |
true if P2G should check for updates and write a log message if a new release is available. If using the UI this message will display there as well. |
Format Config
This section provides settings related to conversions and what formats should be created/saved. P2G supports converting Peloton workouts into a variety of different formats. P2G also lets you choose whether or not you wish to save a local copy when the conversion is completed. This can be useful if you wish to backup your workouts or upload them manually to a different service other than Garmin.
"Format": {
"Fit": true,
"Json": false,
"Tcx": false,
"SaveLocalCopy": false,
"IncldudeTimeInHRZones": false,
"IncludeTimeInPowerZones": false,
"DeviceInfoPath": "./deviceInfo.xml",
"Cycling": {
"PreferredLapType": "Class_Targets"
},
"Running": {
"PreferredLapType": "Distance"
},
"Rowing": {
"PreferredLapType": "Class_Segments"
},
"Strength": {
"DefaultSecondsPerRep": 3
},
"WorkoutTitleTemplate": "{{PelotonWorkoutTitle}} with {{PelotonInstructorName}}"
}
Field | Required | Default | UI Setting Location | Description |
---|---|---|---|---|
Fit | no | false |
Conversion Tab |
true indicates you wish downloaded workouts to be converted to FIT |
Json | no | false |
Conversion Tab |
true indicates you wish downloaded workouts to be converted to JSON. This will automatically save a local copy when enabled. |
Tcx | no | false |
Conversion Tab |
true indicates you wish downloaded workouts to be converted to TCX |
SaveLocalCopy | no | false |
Conversion > Advanced |
true will save any converted workouts to your specified OutputDirectory |
IncludeTimeInHRZones | no | false |
Conversion > Advanced |
Only use this if you are unable to configure your Max HR on Garmin Connect. When set to True, P2G will attempt to capture the time spent in each HR Zone per the data returned by Peloton. See understanding custom zones. |
IncludePowerInHRZones | no | false |
Conversion > Advanced |
Only use this if you are unable to configure your FTP and Power Zones on Garmin Connect. When set to True, P2G will attempt to capture the time spent in each Power Zone per the data returned by Peloton. See understanding custom zones. |
DeviceInfoPath | no | null |
Conversion > Advanced |
The path to your deviceInfo.xml file. See providing device info |
Cycling | no | null |
none | Configuration specific to Cycling workouts. |
Cycling.PreferredLapType | no | Default |
Conversion Tab |
The preferred lap type to use. |
Running | no | null |
none | Configuration specific to Running workouts. |
Running.PreferredLapType | no | Default |
Conversion Tab |
The preferred lap type to use. |
Rowing | no | null |
none | Configuration specific to Rowing workouts. |
Rowing.PreferredLapType | no | Default |
Conversion Tab |
The preferred lap type to use. |
Strength | no | null |
Conversion Tab |
Configuration specific to Strength workouts. |
Strength.DefaultSecondsPerRep | no | 3 |
Conversion Tab |
For exercises that are done for time instead of reps, P2G can estimate how many reps you completed using this value. Ex. If DefaultSecondsPerRep=3 and you do Curls for 15s, P2G will estimate you completed 5 reps. |
WorkoutTitleTemplate | no | {{PelotonWorkoutTitle}} with {{PelotonInstructorName}} |
Conversion Tab |
Allows you to customize how your workout title will appear in Garmin Connect using Handlebars templates. Read More... |
Understanding Custom Zones
Garmin Connect expects that users have a registered device and they expect users have set up their HR and Power Zones on that device. However, this presents a problem if you either:
- A) do not have a device capable of tracking Power
- B) do not have a Garmin device at all.
The most common scenario for Peloton users is scenario A
, where they do not own a Power capable Garmin device and therefore are not able to configure their Power Zones in Garmin Connect. If you do not have Power or HR zones configured in Garmin Connect then you are not able to view accurate Time In Zones
charts for a given workout.
P2G provides a work around for this by optionally enriching the workout with the Time In Zones
data with one caveat: the chart will not display the range value for the zone.
This is only available when generating and uploading the FIT format.
Custom Device Info
By default, P2G using a custom device when converting and upload workouts. This device information is needed in order to count your Peloton workouts towards Challenges and Badges on Garmin. However, you may observe on Garmin Connect that your Peloton workouts will show a device image that does not match your personal device.
If you choose, you can provide P2G with your personal Device Info which will cause the Garmin workout to show the correct to device. Note, this is completely optional and is only for cosmetic preference, your workout will be converted, uploaded, and counted towards challenges regardless of whether this matches your personal device.
See configuring device info for detailed steps on how to create your deviceInfo.xml
.
Lap Types
P2G supports several different strategies for creating Laps in Garmin Connect. If a certain strategy is not available P2G will attempt to fallback to a different strategy. You can override this behavior by specifying your preferred Lap type in the config. When PreferredLapType
is set, P2G will first attempt to generate your preferred type and then fall back to the default behavior if it is unable to. By default P2G will:
- First try to create laps based on
Class_Targets
- Then try to create laps based on
Class_Segments
- Finally fallback to create laps based on
Distance
Strategy | Config Value | Description |
---|---|---|
Class Targets | Class_Targets |
If the Peloton data includes Target Cadence information, then laps will be created to match any time the Target Cadence changed. You must use this strategy if you want the Target Cadence to show up in Garmin on the Cadence chart. |
Class Segments | Class_Segments |
If the Peloton data includes Class Segment information, then laps will be created to match each segment: Warm Up, Cycling, Weights, Cool Down, etc. |
Distance | Distance |
P2G will caclulate Laps based on distance for each 1mi, 1km, or 500m (for Row only) based on your distance setting in Peloton. |
Workout Title Templating
Some characters are not allowed to be used in the workout titles. If you use these characters in your configuration they will automatically be replaced with -
. Additionally, Garmin has a limit on how long a title will be. If the title exceeds this limit (~45 characters) then the title will be truncated.
The below data fields are available for use in the template:
PelotonWorkoutTitle
- Peloton provides this usually in the form of "10 min HITT Ride"PelotonInstructorName
- Peloton provides this as the full instructors name: "Ally Love"
Peloton Config
This section provides settings related to fetching workouts from Peloton.
"Peloton": {
"Email": "peloton@gmail.com",
"Password": "peloton",
"NumWorkoutsToDownload": 1,
"ExcludeWorkoutTypes": [ "meditation" ]
}
Warning
Console or Docker Headless: Your username and password for Peloton and Garmin Connect are stored in clear text, which is not secure. Please be aware of the risks.
WebUI version 3.3.0: Credentials are stored encrypted.
GitHub Actions: Credentials are stored encrypted.
Field | Required | Default | UI Setting Location | Description |
---|---|---|---|---|
yes | null |
Peloton Tab |
Your Peloton email used to sign in | |
Password | yes | null |
Peloton Tab |
Your Peloton password used to sign in. Note: Does not support \ character in password |
NumWorkoutsToDownload | no | 5 | Peloton Tab |
The default number of workouts to download. See choosing number of workouts to download. Set this to 0 if you would like P2G to prompt you each time for a number to download. |
ExcludeWorkoutTypes | no | none | Peloton Tab |
A comma separated list of workout types that you do not want P2G to download/convert/upload. See example use cases below. |
Choosing Number of Workouts To Download
When choosing the number of workouts P2G should download each polling cycle its important to keep your configured PollingInterval in mind. If, for example, your polling interval is set to hourly, then you may want to set NumWorkoutsToDownload
to 4 or greater. This ensures if you did four 15min workouts during that hour they would all be captured.
Exclude Workout Types
Example use cases:
- You take a wide variety of Peloton classes, including meditation and you want to skip uploading meditation classes.
- You want to avoid double-counting activities you already track directly on a Garmin device, such as outdoor running workouts.
The available values are:
Cycling
Outdoor Cycling
BikeBootcamp
TreadmillRunning
OutdoorRunning
TreadmillWalking
OutdoorWalking
Cardio
Circuit
Strength
Stretching
Yoga
Meditation
Garmin Config
This section provides settings related to uploading workouts to Garmin.
"Garmin": {
"Email": "garmin@gmail.com",
"Password": "garmin",
"TwoStepVerificationEnabled": false,
"Upload": false,
"FormatToUpload": "fit"
}
Warning
Console or Docker Headless: Your username and password for Peloton and Garmin Connect are stored in clear text, which is not secure. Please be aware of the risks.
WebUI version 3.3.0: Credentials are stored encrypted.
GitHub Actions: Credentials are stored encrypted.
Field | Required | Default | UI Setting Location | Description |
---|---|---|---|---|
yes - if Upload=true | null |
Garmin Tab |
Your Garmin email used to sign in | |
Password | yes - if Upload=true | null |
Garmin Tab |
Your Garmin password used to sign in. Note: Does not support \ character in password |
TwoStepVerificationEnabled | no | false |
Garmin Tab |
Whether or not your Garmin account is protected by Two Step Verification |
Upload | no | false |
Garmin Tab |
true indicates you wish downloaded workouts to be automatically uploaded to Garmin for you. |
FormatToUpload | no | fit |
Garmin Tab > Advanced |
Valid values are fit or tcx . Ensure the format you specify here is also enabled in your Format config |
Observability Config
P2G supports publishing OpenTelemetry Metrics, Logs, and Trace. This section provides settings related to those pillars.
The Observability config section contains three main sub-sections:
- Prometheus - Metrics
- Jaeger - Traces
- Serilog - Logs
"Observability": {
"Prometheus": {
"Enabled": false,
"Port": 4000
},
"Jaeger": {
"Enabled": false,
"AgentHost": "localhost",
"AgentPort": 6831
},
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": "Information",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "./output/log.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 7
}
}
]
}
}
Prometheus Config
"Prometheus": {
"Enabled": false,
"Port": 4000
}
Field | Required | Default | Description |
---|---|---|---|
Enabled | no | false |
Whether or not to expose metrics. Metrics will be available at http://localhost:{port}/metrics |
Port | no | 80 |
The port the metrics endpoint should be served on. Only valid for Console mode, not Api/WebUI |
If you are using Docker, ensure you have exposed the port from your container.
Example Prometheus scraper config
- job_name: 'p2g'
scrape_interval: 60s
static_configs:
- targets: [<p2gIPaddress>:<p2gPort>]
tls_config:
insecure_skip_verify: true
Jaeger Config
"Jaeger": {
"Enabled": false,
"AgentHost": "localhost",
"AgentPort": 6831
}
Field | Required | Default | Description |
---|---|---|---|
Enabled | no | false |
Whether or not to generate traces. |
AgentHost | yes - if Enalbed=true | null |
The host address for your trace collector. |
AgentPort | yes - if Enabled=true | null |
The port for your trace collector. |
Serilog Config
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Grafana.Loki" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Error",
"System": "Error"
}
},
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "./output/log.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 7
}
},
{
"Name": "GrafanaLoki",
"Args": {
"uri": "http://192.168.1.95:3100",
"textFormatter": "Serilog.Sinks.Grafana.Loki.LokiJsonTextFormatter, Serilog.Sinks.Grafana.Loki",
"labels": [
{
"key": "app",
"value": "p2g"
}
]
}
}]
}
Field | Required | Default | Description |
---|---|---|---|
Using | no | null |
A list of sinks you would like use. The valid sinks are listed in the examplea above. |
MinimumLevel | no | null |
The minimum level to write. [Verbose, Debug, Information, Warning, Error, Fatal] |
WriteTo | no | null |
Additional config for various sinks you are writing to. |
More detailed information about configuring Logging can be found on the Serilog Config Repo.