For the Node Red guys out there, here are my Fan flow automations, depending on the workout type and equipment bike/tread a number of fans will turn on and off after x mins depending on the class lengh.
I follow the implementation however Iād rather just bounce off what others have done. Can anyone post a config.yaml examlpe with all the components elements successfully setup?
Is there a better setup guide to follow for newbs? I followed the github page by adding folders and pasting in the code. After that Iām lost. Trying to piece together bits from this thread but Iām not getting anywhere.
I recommend using hacs, copying the folder and text did not work for me
I was just looking at how to display some of this data better using the Influxdb and Iām running into a few hurdles because of how the data reports.
- Once you finish a workout, the sensor still holds the last value. So I canāt figure out how to do things like show calories over the last day, etc. For example, yesterday I did a 30 minute ride, and then a 5 minute cool down:
SELECT "Distance Mi","Calories KCal" FROM "homeassistant"."autogen"."state"
WHERE time > now() - 24h AND "entity_id"='peloton_xyz_com'
and "state"='Complete'
- It would be nice if the integration included non-aggregate figures per update as well. For example, when I look in Influxdb right now, each report is the running total (which is also helpful, just not for this):
SELECT "Distance Mi","Calories KCal" FROM "homeassistant"."autogen"."state"
WHERE time > now() - 24h AND "entity_id"='peloton_xyz_com'
and "state"!='Complete'
However, you canāt easily SUM()
that over a year to create summary statistics. I was thinking of making a dashboard similar to how the energy dashboard sums stuff up, but I canāt seem to make the data work. If you have better suggestions on how to accomplish this, Iāll change course, it just seemed like this would be the best method. Thanks!
It may be easier to import your data to InfluxDB via NodeJS (and peloton-client-node). Home Assistant doesnāt do a great job of allowing integrations to import a series of related data points. I think thatās why the Energy feature had to be built in the first place. IMO even showing stats from the last workout pushes HA to its limits.
The API returns nice data for each workout. The below is an excerpt from mine:
{
"duration": 1200,
"is_class_plan_shown": true,
"segment_list": [
{
"id": "560f9ba8890f447dabc743dacb6bc695",
"length": 363,
"start_time_offset": 0,
"icon_url": "https://s3.amazonaws.com/static-cdn.pelotoncycle.com/segment-icons/warmup.png",
"intensity_in_mets": 3.5,
"metrics_type": "cycling",
"icon_name": "warmup",
"icon_slug": "warmup",
"name": "Warm Up",
"is_drill": false
},
{
"id": "23c14866ec4547fa8fc716070fc74a8e",
"length": 777,
"start_time_offset": 363,
"icon_url": "https://s3.amazonaws.com/static-cdn.pelotoncycle.com/segment-icons/cycling.png",
"intensity_in_mets": 6.0,
"metrics_type": "cycling",
"icon_name": "cycling",
"icon_slug": "cycling",
"name": "Cycling",
"is_drill": false
},
{
"id": "1a5eea7c49d542fcaa4123ebf8e4c08e",
"length": 60,
"start_time_offset": 1140,
"icon_url": "https://s3.amazonaws.com/static-cdn.pelotoncycle.com/segment-icons/cooldown.png",
"intensity_in_mets": 3.5,
"metrics_type": "cycling",
"icon_name": "cooldown",
"icon_slug": "cooldown",
"name": "Cool Down",
"is_drill": false
}
],
"seconds_since_pedaling_start": [
1, 51, 101, 151, 201, 251, 301, 351, 401, 451, 501, 551, 601, 651, 701, 751,
801, 851, 901, 951, 1001, 1051, 1101, 1151, 1199
],
"average_summaries": [
{
"display_name": "Avg Output",
"display_unit": "watts",
"value": 75,
"slug": "avg_output"
},
{
"display_name": "Avg Cadence",
"display_unit": "rpm",
"value": 72,
"slug": "avg_cadence"
},
{
"display_name": "Avg Resistance",
"display_unit": "%",
"value": 36,
"slug": "avg_resistance"
},
{
"display_name": "Avg Speed",
"display_unit": "mph",
"value": 14.0,
"slug": "avg_speed"
}
],
"summaries": [
{
"display_name": "Total Output",
"display_unit": "kj",
"value": 89,
"slug": "total_output"
},
{
"display_name": "Distance",
"display_unit": "mi",
"value": 4.67,
"slug": "distance"
},
{
"display_name": "Calories",
"display_unit": "kcal",
"value": 226,
"slug": "calories"
}
],
"metrics": [
{
"display_name": "Output",
"display_unit": "watts",
"max_value": 186,
"average_value": 75,
"values": [
46, 40, 43, 84, 90, 108, 111, 107, 78, 94, 87, 86, 133, 177, 136, 89,
101, 106, 114, 81, 88, 114, 166, 37, 31
],
"slug": "output"
},
{
"display_name": "Cadence",
"display_unit": "rpm",
"max_value": 112,
"average_value": 72,
"values": [
89, 83, 82, 81, 76, 78, 82, 87, 78, 78, 76, 74, 71, 68, 76, 74, 74, 72,
76, 82, 79, 79, 111, 94, 84
],
"slug": "cadence"
},
{
"display_name": "Resistance",
"display_unit": "%",
"max_value": 60,
"average_value": 36,
"values": [
25, 25, 26, 39, 38, 40, 40, 38, 36, 41, 41, 42, 52, 60, 49, 39, 42, 45,
45, 35, 41, 41, 38, 20, 20
],
"slug": "resistance"
},
{
"display_name": "Speed",
"display_unit": "mph",
"max_value": 20.8,
"average_value": 14.0,
"values": [
11.6, 10.8, 11.2, 15.1, 15.5, 16.8, 16.9, 16.7, 14.7, 15.8, 15.3, 15.3,
18.3, 20.4, 18.4, 15.5, 16.3, 16.6, 17.2, 14.9, 15.4, 17.1, 19.9, 10.3,
9.5
],
"slug": "speed"
},
{
"display_name": "Heart Rate",
"display_unit": "bpm",
"max_value": 152,
"average_value": 125,
"values": [
110, 109, 113, 110, 118, 123, 123, 133, 125, 126, 121, 116, 141, 145,
145, 132, 136, 137, 141, 139, 131, 139, 152, 152, 136
],
"slug": "heart_rate",
"zones": [
{
"display_name": "Zone 1",
"slug": "zone1",
"range": "<119 bpm",
"duration": 364,
"max_value": 118,
"min_value": 0
},
{
"display_name": "Zone 2",
"slug": "zone2",
"range": "119-137 bpm",
"duration": 659,
"max_value": 137,
"min_value": 119
},
{
"display_name": "Zone 3",
"slug": "zone3",
"range": "138-155 bpm",
"duration": 174,
"max_value": 155,
"min_value": 138
},
{
"display_name": "Zone 4",
"slug": "zone4",
"range": "156-173 bpm",
"duration": 0,
"max_value": 173,
"min_value": 156
},
{
"display_name": "Zone 5",
"slug": "zone5",
"range": ">=174 bpm",
"duration": 0,
"max_value": 184,
"min_value": 174
}
],
"missing_data_duration": 3
}
],
"has_apple_watch_metrics": false,
"location_data": [],
"is_location_data_accurate": null,
"splits_data": {
"distance_marker_display_unit": "mi",
"elevation_change_display_unit": "ft",
"splits": [
{
"distance_marker": 1.0,
"order": 1,
"seconds": 291.0,
"elevation_change": null,
"is_best": false
},
{
"distance_marker": 2.0,
"order": 2,
"seconds": 258.0,
"elevation_change": null,
"is_best": false
},
{
"distance_marker": 3.0,
"order": 3,
"seconds": 234.0,
"elevation_change": null,
"is_best": true
},
{
"distance_marker": 4.0,
"order": 4,
"seconds": 244.0,
"elevation_change": null,
"is_best": false
},
{
"distance_marker": 0.67,
"order": 5,
"seconds": 171.0,
"elevation_change": null,
"is_best": false
}
]
},
"splits_metrics": {},
"target_performance_metrics": {
"target_graph_metrics": [
{
"graph_data": {
"upper": [
90, 90, 90, 90, 75, 75, 75, 75, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 80, 65, 65, 100
],
"lower": [
70, 70, 70, 70, 70, 70, 70, 70, 60, 60, 60, 60, 60, 60, 60, 60, 60,
60, 60, 60, 70, 60, 60, 80
],
"average": [
80, 80, 80, 80, 72, 72, 72, 72, 62, 62, 62, 62, 62, 62, 62, 62, 62,
62, 62, 62, 75, 62, 62, 90
]
},
"max": 100,
"min": 60,
"average": 69,
"type": "cadence"
},
{
"graph_data": {
"upper": [
30, 30, 30, 36, 40, 40, 42, 42, 38, 38, 44, 35, 50, 50, 50, 40, 45,
50, 50, 35, 35, 45, 35, 30
],
"lower": [
20, 20, 20, 24, 35, 35, 36, 36, 32, 32, 36, 30, 40, 43, 43, 35, 37,
39, 41, 30, 30, 40, 30, 20
],
"average": [
25, 25, 25, 30, 37, 37, 39, 39, 35, 35, 40, 32, 45, 46, 46, 37, 41,
44, 45, 32, 32, 42, 32, 25
]
},
"max": 50,
"min": 20,
"average": 36,
"type": "resistance"
}
],
"cadence_time_in_range": 57,
"resistance_time_in_range": 86
},
"target_metrics_performance_data": {
"target_metrics": [
{
"offsets": { "start": 60, "end": 178 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 30.0, "lower": 20.0 },
{ "name": "cadence", "upper": 90.0, "lower": 70.0 }
]
},
{
"offsets": { "start": 179, "end": 190 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 33.0, "lower": 22.0 },
{ "name": "cadence", "upper": 90.0, "lower": 70.0 }
]
},
{
"offsets": { "start": 191, "end": 241 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 36.0, "lower": 24.0 },
{ "name": "cadence", "upper": 90.0, "lower": 70.0 }
]
},
{
"offsets": { "start": 242, "end": 315 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 40.0, "lower": 35.0 },
{ "name": "cadence", "upper": 75.0, "lower": 70.0 }
]
},
{
"offsets": { "start": 316, "end": 369 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 42.0, "lower": 36.0 },
{ "name": "cadence", "upper": 75.0, "lower": 70.0 }
]
},
{
"offsets": { "start": 370, "end": 397 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 40.0, "lower": 35.0 },
{ "name": "cadence", "upper": 75.0, "lower": 70.0 }
]
},
{
"offsets": { "start": 398, "end": 432 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 42.0, "lower": 36.0 },
{ "name": "cadence", "upper": 75.0, "lower": 70.0 }
]
},
{
"offsets": { "start": 433, "end": 456 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 35.0, "lower": 30.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 457, "end": 517 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 38.0, "lower": 32.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 518, "end": 533 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 41.0, "lower": 34.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 534, "end": 588 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 44.0, "lower": 36.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 589, "end": 612 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 35.0, "lower": 30.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 613, "end": 648 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 40.0, "lower": 33.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 649, "end": 656 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 35.0, "lower": 30.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 657, "end": 676 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 50.0, "lower": 40.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 677, "end": 731 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 50.0, "lower": 43.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 732, "end": 748 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 50.0, "lower": 40.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 749, "end": 786 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 50.0, "lower": 43.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 787, "end": 825 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 40.0, "lower": 35.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 826, "end": 886 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 45.0, "lower": 37.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 887, "end": 933 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 50.0, "lower": 39.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 934, "end": 981 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 50.0, "lower": 41.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 982, "end": 1043 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 35.0, "lower": 30.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 1044, "end": 1082 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 35.0, "lower": 30.0 },
{ "name": "cadence", "upper": 80.0, "lower": 70.0 }
]
},
{
"offsets": { "start": 1083, "end": 1114 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 45.0, "lower": 40.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 1115, "end": 1146 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 45.0, "lower": 40.0 },
{ "name": "cadence", "upper": 80.0, "lower": 70.0 }
]
},
{
"offsets": { "start": 1147, "end": 1163 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 35.0, "lower": 30.0 },
{ "name": "cadence", "upper": 65.0, "lower": 60.0 }
]
},
{
"offsets": { "start": 1164, "end": 1172 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 35.0, "lower": 30.0 },
{ "name": "cadence", "upper": 90.0, "lower": 80.0 }
]
},
{
"offsets": { "start": 1173, "end": 1186 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 40.0, "lower": 35.0 },
{ "name": "cadence", "upper": 90.0, "lower": 80.0 }
]
},
{
"offsets": { "start": 1187, "end": 1202 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 50.0, "lower": 45.0 },
{ "name": "cadence", "upper": 100.0, "lower": 90.0 }
]
},
{
"offsets": { "start": 1203, "end": 1260 },
"segment_type": "cycling",
"metrics": [
{ "name": "resistance", "upper": 30.0, "lower": 20.0 },
{ "name": "cadence", "upper": 100.0, "lower": 80.0 }
]
}
],
"time_in_metric": [
{ "name": "resistance", "value": 86 },
{ "name": "cadence", "value": 57 }
]
},
"effort_zones": {
"total_effort_points": 11.9,
"heart_rate_zone_durations": {
"heart_rate_z1_duration": 364,
"heart_rate_z2_duration": 659,
"heart_rate_z3_duration": 174,
"heart_rate_z4_duration": 0,
"heart_rate_z5_duration": 0
}
},
"muscle_group_score": [
{
"muscle_group": "biceps",
"score": 777.0,
"percentage": 6,
"bucket": 1,
"display_name": "Biceps"
},
{
"muscle_group": "calves",
"score": 1554.0,
"percentage": 11,
"bucket": 2,
"display_name": "Calves"
},
{
"muscle_group": "core",
"score": 1554.0,
"percentage": 11,
"bucket": 2,
"display_name": "Core"
},
{
"muscle_group": "glutes",
"score": 2331.0,
"percentage": 17,
"bucket": 3,
"display_name": "Glutes"
},
{
"muscle_group": "hamstrings",
"score": 2331.0,
"percentage": 17,
"bucket": 3,
"display_name": "Hamstrings"
},
{
"muscle_group": "hips",
"score": 1554.0,
"percentage": 11,
"bucket": 2,
"display_name": "Hips"
},
{
"muscle_group": "quads",
"score": 2331.0,
"percentage": 17,
"bucket": 3,
"display_name": "Quads"
},
{
"muscle_group": "shoulders",
"score": 777.0,
"percentage": 5,
"bucket": 1,
"display_name": "Shoulders"
},
{
"muscle_group": "triceps",
"score": 777.0,
"percentage": 5,
"bucket": 1,
"display_name": "Triceps"
}
]
}
Thereās also an endpoint that lets you pull summary data for the last several workouts.
If you still want to use the HA integration, you could either have InfluxDB key off of the workout start time and end time or adjust your query to group by those same parameters. The DB would then consider any workout with the same start and end time as an existing entry to be a duplicate that would be ignored.
Updated to the newest HACs version today which is now configurable via HA integrations. Updated all the applicable entities/dashboards and have been able to properly show, amongst other things, the workout status and workout type. The only problem is that when a workout starts, everything (all attributes) go into an unavailable status and as I result, my automations do not work. Once the workout is complete, however, it does update the dashboard with all the correct/latest workout states. Is this a bug that others are experiencing as well or am I missing something?
Nope, itās a bug. Sorry about that! I submitted a PR to fix this at https://github.com/edwork/homeassistant-peloton-sensor/pull/43. @edwork, can you take a look?
(Thereās a second, unrelated PR, as well: https://github.com/edwork/homeassistant-peloton-sensor/pull/42.)
Outstandingā¦all appears to be working fine now with the fix implemented. Great work, thank you!!
That makes sense. Good idea, Iāll look into scripting it outside of HA. Perhaps I could have HA trigger an automation when I finish a workout that would then push the summary data into Influx. Thanks!
Hi all,
quick question, can someone confirm if the new version of the integration (8.0+) can support multiple profiles? It doesnāt seem possible via the gui setup screen and it used to be possible using the old yaml config. If itās not then Iāll look to raise as an issue as this was a useful feature in my setup.
Cheers
Spence
It does. You should be able to just add the integration a second time using the GUI, logging in as the new user:
If that doesnāt work, try deleting the existing GUI-created profile and make sure that you delete your old config from configuration.yaml. Then reboot and add from the GUI again.
That worked, cheers!
Awesome! For anyone running into similar weird issues with the integration, just be aware that you need to manually switch from the .yaml-based config to the GUI-based config for the plugin to work reliably.
Iām having issues running the HACS integration. I previously had the custom_components integration working. Iāve deleted that folder from custom_components, deleted the config.yaml credentials, rebooted, then added the repository in HACS and installed 0.8.1, but after a reboot I can not find āPelotonā in āAdd Integrationā. I have many HACS components running, so Iām confident Iāve followed the right steps (until Iām notā¦).
Any chance thereās an issue in Home Assistant 2022.8.6 that I may be running into? Maybe something else I missed?
I see the last post here is from July so thatās the only thing I can see different.
I tried again today and Peloton now drops down. I didnāt change anything, so seems to have just taken time to propagate. Weird.
I cantā seem to get the BPM sensor to work. My goal is to adjust overhead RGB lights based on heart rate BPM.
Hereās my sensor
- sensor:
peloton_bpm:
icon_template: mdi:heart-pulse
friendly_name: "Peloton BPM"
unit_of_measurement: BPM
value_template: >
{{ state_attr('sensor.name_here', "Heart Rate Bpm")}}
Any ideas?
Anyone got the Yesoul bike working? I know this is a different bike but I think the Yesoul may be a copy of it?
I cant get this add on to work keep getting
Error
Config flow could not be loaded: 500 Internal Server Error Server got itself in trouble
Anyone any ideas please ?
Hi, Iām brand new to HA. I was wondering if thereās a way to have RGB lighting around my Peloton to light up in the same colour of light that the studio on screen is using to make it feel more immersive?