karaul / fitplotter

Plot and compare data recorded in the binary FIT (Garmin) and TKL files
MIT License
12 stars 2 forks source link

Incorporating more values #6

Closed rucksman closed 7 months ago

rucksman commented 9 months ago

Hi,

obviously your project was tailormade for you needs (running) which is perfectly fine. I want to add some additional values from my activities, especially "rear_gear_change" (cycling). Problem is, that this is not found in "records" but in "events". Events have their own timestamp, so I would have to somehow add these timestamps to the timestamps of "records" and display "rear_gear_change" then in the map. To be honest I would need some push in the right direction from you .... If needed I can provide the relevant part of my fit file. Thanks a lot!

karaul commented 9 months ago

Hi

If needed I can provide the relevant part of my fit file

Yes, please send the *.fit file. I am travelling till the Russian New Year (Jan 14) being now in Russia, but since I have an access to the gmale and Git, I can think how to fix it.

Happy New Year!

rucksman commented 9 months ago

I invested some time today to understand the functionality, but I did not find the exact point where to insert the new values. I see that I have to create a new array in "chartdata" (function getDataFromFitForCanvasJS). From what I see in the code the array comes from the options in ylist. But I did not clearly see where the list is filled from. This is probably due to the fact that I already modified the code a little bit to fit my needs (I have 2 arrays in chartdata: heart rate and speed).

This is how my fit file looks like after parsing. Shortened and redacted it due to privacy reasons, but it should be enough to see how the values look like:

{
  "activity": {
    "sessions": [
      {
        "laps": [
          {
            "records": [
              {
                "timestamp": "2023-12-29T10:36:05.000Z",
                "elapsed_time": 0,
                "timer_time": 0,
                "position_lat": ...,
                "position_long": ...,
                "distance": 0.00027,
                "altitude": 0.04660000000000002,
                "speed": 0,
                "heart_rate": 159,
                "temperature": -257.15
              },
              ...
            ],
            "lengths": []
          }
        ]
      }
    ],
    "events": [
      {
        "timestamp": "2023-12-29T10:36:05.000Z",
        "data": 0,
        "event": "timer",
        "event_type": "start",
        "event_group": 0
      },
      {
        "timestamp": "2023-12-29T10:36:05.000Z",
        "data": 671159047,
        "event": "rear_gear_change",
        "event_type": "marker"
      },
      ...
    ],
    "hrv": [],
    "device_infos": [
    ],
    "developer_data_ids": [],
    "field_descriptions": [],
    "sports": [
      { "name": "GRAVEL", "sport": "cycling", "sub_sport": "gravel_cycling" }
    ]
  }
}

The vaule most interesting is in "events" and has the event type "rear_gear_change". I have to check in the official Garmin SDK what kind of data this is because of course this should be an integer between 1 and 12.

So it would be very nice if you could give me a hint how to add these values as a new array in chartdata. I want to upgrade my bike also with a powermeter, so it would be useful for me to understand how the chartdata object is created in order to be able to add power data on my own without having to bother you again.

karaul commented 9 months ago

If your metric is the averaged one between events, then the x-axis must be laps.

Select in x-axis droplisr lap-number, and then check metrics in the y-axis droplet.

To say more definitely, I need your fit file.

karaul commented 9 months ago

but I did not find the exact point where to insert the new values

The metrics are collected automatically by scanning the fit file, function prepareFitData, line 645

karaul commented 9 months ago

Probably, you can add into the function prepareFitData a cycle like for (let k in data.events) { ...} to fill the needed metric from events section

rucksman commented 9 months ago

If your metric is the averaged one between events, then the x-axis must be laps.

Select in x-axis droplisr lap-number, and then check metrics in the y-axis droplet.

This does not work. If I change to lap_number, I have the options "event" and "event_type" in the dropdown. Both options show no data in the plot. I do not know what you mean by "metric is the averaged one between events". Obviously the "rear_gear_change" is an event that occurs when I change gears on the bike. So the timestamp does not match with the timestamps in records (only by a mere coincedence). So in the example from my post above, I did change gears here:

{
        "timestamp": "2023-12-29T10:36:05.000Z",
        "data": 671159047,
        "event": "rear_gear_change",
        "event_type": "marker"
},

data is uint8z according to the FitSDK. Will try to add a for loop, only the x field worries me. I have to check how you calculate this out of distance.

karaul commented 9 months ago

what you mean by "metric is the averaged one between events"

It was my mistake. The section events is not checked in prepareFitData.

rucksman commented 9 months ago

Having a hard time to figure out how it could work ...

Added the following right after the loop for data.laps (around line 683):

for (let k in data.events) {
  if (data.events[k].event == 'rear_gear_change') {
    let event = data.events[k];
    D = new Date(event.timestamp);
    data.records[k].timestamp = D.getHours() + D.getMinutes() / 60 - timeoffset;
    data.records[k].gear = event.data;
  }
}

Now I have gear data in data.records. Problem now is that this data is not correctly shown in the chart. In my already modified view I only show speed and heart_rate on the y-axis (now gear as well) and distance on the x-axis. While speed and heart_rate appear in the chart at the right place related to distance, gear values are shown more or less one after the other right from the beginning until the amount of gear changes is reached (~50). So gear values are not properly displayed in relation to distance. So data.records[k].timestamp is wrong which is quite obvious as the counters (k) for records and events do not match . How and where do I have to make modifications to get the correct x-value (meaning pushing the gear change events to the correct place in the records array)? Second question: is there already a helper function somewhere in the project for converting uint8z values to correct values?

karaul commented 9 months ago

Explore my function getDataFromFitForCanvasJS, line 216., it is called from line 396. You see there a check for x-axis, e.g. line 218. Introduce a flag variable for the gear, e.g. if (fieldx === "timestamp_gear"){ here is the code to put data for the chart, put here gear's timestamps, as in line 221}

The second question

data is uint8z according to the FitSDK. Will try to add a for loop, only the x field worries me. I have to check how you calculate this out of distance

Do you mean out of the track (if not give me more explanations what do you want)? You have in the *.fit file { "timestamp": "2023-12-29T10:36:05.000Z", "data": 0, "event": "timer", "event_type": "start", "event_group": 0 }, the event_type": "start", and the corresponding timestamp. Check other timestamps with the "start" timestamp, to recognize whether the gear change before or after "start" event.

rucksman commented 9 months ago

More confused than before. What is the difference between the code I entered around line 683 and the code you proposed in 218? I tried some variations, but no luck.

Just use one of your own .fit files. I had a look to the one in this repo (2021-01-26T17_13_43+00_00_6171809523.fit). There are 8 elements in the events array. My array looks like this: image So if you use for example the "undefined" events in your array as an equivalent to my "rear_gear_change" event, you can try to incorporate those values. This would be really of great help as I am stuck somehow at the moment.