I have made a Pull Request introduces a new functionality for the Train view: the ability to add custom charts based on HTML/JS source code, linked in real-time with the training telemetry.
With this feature, athletes are no longer limited to predefined charts or telemetry fields when training in GC. They can now design awesome, dynamic charts that react to live telemetry—such as histograms, maps, dials, and more. Even without extensive knowledge of HTML/JS, users can easily achieve great results by leveraging generic web design tools or AI-based HTML code generators.
For developers of html, the PR HTML Chart in train view documents its usage. It is nos complete, and until it is (hopefully) in GC binary, that documentation can be a starting point. Afterwards, GC wiki will have the documentation.
In this PR, Python charts for training and Web charts hability to use telemetry updates in training functionalities have not been included, for the sake of clarity of the PR and not mixing functionalities in the PR. It was initially presented with those charts included, but finally they where removed of the PR.
The HTML Chart provides a split-pane interface allowing users to write and preview their charts instantly:
Configuration and html code are stored along the rest of the tiles of a view in training.
HTML code of the charts could be uploaded to the cloud as well as python charts can, to be shared with other users.
Example CodeBelow is the default template code generated for any new HTML chart. It serves as a simple example of how to connect to the bridge, parse the telemetry payload, and update the UI in real-time:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="qrc:///qtwebchannel/qwebchannel.js"></script> <style>body{font-family:sans-serif;padding:12px;color:#333}</style> </head> <body> <h2>GC WebChannel</h2> <div>Speed: <b id="speed">0.0</b> km/h</div> <div>Power: <b id="power">0</b> W</div> <div>HR: <b id="hr">0</b> bpm</div> <div>Cadence: <b id="cad">0</b> rpm</div> <div>Distance: <b id="dist">0.00</b> km</div> <div>State: <b id="state">Stopped</b></div> <script> if (typeof QWebChannel !== 'undefined') { new QWebChannel(qt.webChannelTransport, function(channel) { window.gc = channel.objects.gc; if (window.gc.telemetry) { window.gc.telemetry.connect(function(payload) { var d = typeof payload === 'string' ? JSON.parse(payload) : payload; document.getElementById("speed").innerText = (d.speed_kmh || 0).toFixed(1); document.getElementById("power").innerText = Math.round(d.power_w || 0); document.getElementById("hr").innerText = Math.round(d.hr_bpm || 0); document.getElementById("cad").innerText = Math.round(d.cadence_rpm || 0); document.getElementById("dist").innerText = (d.distance_km || 0).toFixed(2); }); } if (window.gc.stateChanged) { window.gc.stateChanged.connect(function(state) { document.getElementById("state").innerText = state.toUpperCase(); }); } }); } </script> </body> </html> Tests and feedback from the usersAs said, anyone without html knowledge can potentially create html views, using AI, for example (that is may case).
There are no restrictions on creating, for example, a view similar to the one shown in this issue: Gauge view in train mode
, referenced in the PR.
Although in that case, we will need to extend the current configuration and telemetry data provided to html: workout text messages defined at specific times, target power of the current lap, duration of the workout and its full definition, etc; things that will be added in next deliveries if there is interest, I guess.
This functionality is not closed with this PR.
Therefore, I’d appreciate any feedback. Binaries will be available soon, Ale is launching a build.
I am attaching the two html charts that I am showing in the video.
Please note that they are not final versions nor official files. They were created to test behavior of the code during development. In fact, unfortunately, the code for the map is mostly in spanish (sorry for that), as it was a test.
In the header of the map code, there is a description of the current variables that can be used to model the behavior of the page, in the configuration section of the chart.
I am also adding them to the tests charts of the project (test/charts path of the project).

lo, Joachim, thanks for those files! I will have a look at them and will use them for my next html for sure.
In the meanwhile, this is the status of the additional data:
sec_msecs_remaining and erg_msecs_remaining have been fetched empirically. I do not understand very well tha naming of accessors/funtions/variables that keep track of them, although they behave as my purpose, the naming does not point to that… (this is open to your more experienced knowledge, and can be changed):
qint64 sec_msecs_remaining = rt.value(RealtimeData::DataSeries::ErgTimeRemaining); qint64 erg_msecs_remaining = rt.value(RealtimeData::DataSeries::LapTimeRemaining);Except target_power_w, sec_msecs_remaining and erg_msecs_remaining that have been tested with ERG workouts and seem ok for me, those additional data have not yet (only coded).
Today it is difficult to progress on this, but I will see.
Regarding performance I do not think it is an issue, in general terms, for the computer. The webchannel is like functions that are invoked and only get data, and events to synchronize calls; html could be hard to run, but if you are conscious of it it is not likely to happen; the first versions of the real time map I put as example needed more time to render than the telemetry events period, so it behaved wrongly: it was re loading all the map tiles, re building the elevations profile, etc. The AI was told to improve it and it did the magic, only updating the trace instead of replotting all, and since then it works smoothy without performance issues in an old laptop (Linux). But, as you say, we must be arare it has been done by AI without any responsability on my side :)
lo, Joachim, thanks for those files! I will have a look at them and will use them for my next html for sure.
- Configured font in config: I do not have a clear idea of this, too. Is there any configuration that can be fetched? Perhaps you mean specific configuration for the chart? In such case, you can add configuration variables at chart level using the interface
- Dark/Light mode: you say GCColor::isDark(GColor(CPLOTBACKGROUND)); and also there is TrainBottom::isDark(), hardcoded to GColor(CCHROME). What do you think is better? You coded both :)
- sec_msecs_remaining: current section milisecs remaining (erg file selected event)
- erg_msecs_remaining: workout milisecs remaining (erg file selected event)
- Workout section text: in progress (I am trying to fetch it and show on telemetry updates), with no success for the moment, but it cannot be difficult.
sec_msecs_remaining and erg_msecs_remaining have been fetched empirically. I do not understand very well tha naming of accessors/funtions/variables that keep track of them, although they behave as my purpose, the naming does not point to that… (this is open to your more experienced knowledge, and can be changed):
qint64 sec_msecs_remaining = rt.value(RealtimeData::DataSeries::ErgTimeRemaining); qint64 erg_msecs_remaining = rt.value(RealtimeData::DataSeries::LapTimeRemaining);

Today it is difficult to progress on this, but I will see.



There is a new snapshot of GC that has modified the fields that telemtry exposes to HTML charts in training, to be more standard with the naming conventions along GC.
Now, all real time data labels exported use its english naming, with some exceptions that have been created for these HTML charts (“Current Position” and “notification_text”)
WARNING! This binary breaks compatibility with existing HTML charts. The previous telemetry data keys did not follow a standard pattern, which was going to make future maintenance difficult.
Sorry the inconveniences, I believe it is worth making this change.
Here is the direct mapping between the keys previously used in HTML charts and their new names:
Old Key New Key msecs Time sec_msecs_remaining Section Time Remaining erg_msecs_remaining Lap Time Remaining erg_time_msecs Current Position lat Latitude lon Longitude alt Altitude slope Slope speed_kmh Speed hr_bpm Heart Rate power_w Power wbal W' bal cadence_rpm Cadence distance_km Distance target_power_w Target PowerHopefully, it is a direct translation.
It must be noticed that some telemetry data make sense only in workouts of type ‘Slope’ and do not in ‘ERG’, and the opposite.Not all real time figures are telemetry data, some are derived metrics that will not have any real value in html charts yet. That is something that will be changed in next deliveries.
Additionally, a new example chart has been added to the repository, so it can be used for testing, for example, to know what keys are available, if they have good figures, etc, as it displays all available telemetry data for testing purposes.

I have modified the three charts that I previously showed in this thread, in case you are already using them, in the attached gcharset (to be imported in Training view); they have incorporated some improvements I have added, and, as always, be aware they have been generated mostly by AI, and the suit my needs, probably they are not general purpose; you can always do modifications on them.
I hope you will enjoy them


