Hacking the FIT

This likely isn't possible... but it sure would be nice. I am using Power data for more performance analysis. But some of my efforts do not include Power. Like on a spin bike, and on my MTB. I can estimate power from HR, gradient, etc. It isn't ideal due to cardiac drift, etc. But it is better than nothing.

Is there a way to write data to the activitiy's FIT file in such a way that the logging S/W that reads the FIT file sees my data field's additions to the FIT file as power meter data?

Thanks!
  • You can use the FIT “nativeNum” functionality to indicate that your developer field is equivalent to native power. Garmin Connect will never treat it as a first class citizen (although of course it displays all developer fields), but some 3rd party sites and apps will, such as Sporttracks, runalyze, Golden Cheetah, ConnectStats, etc. Notably, Strava will ignore power data written this way. (**)

    See the createField() docs:
    https://developer.garmin.com/downloa...nstance_method

    (**) IOW:
    • Garmin Connect:
      Never interprets CIQ developer fields as "native", no matter what you do. Usually displays developer fields (unless there's a bug)

      For example, CIQ apps can't override distance or speed. If a CIQ app records running dynamics, they won't be colored the same way as native running dynamics, in the graph.

      A lot of people (both devs and users) are pretty unhappy about this.
    • Some third party sites:
      Interpret some nativeNum developer fields as "native", which is what developers would prefer (obviously).

      e.g. If your CIQ app records power with the appropriate nativeNum, runalyze will treat it just like native power, and display it in a graph labelled "Power", as well as calculating the Running Effectiveness for you (in the case of running power).
    • Other 3rd party sites:
      Ignore nativeNum developer fields.

      e.g. Strava completely ignores power recorded by CIQ apps - does not even display it

    Additionally, some sites such as Stryd and Smashrun require that the internal name of a developer field is set to “Power”, to be recognized as power. (This applies to “current” power, in the activity graph. I have no idea what label you would need to use for max or avg power, or whether those sites even support anything other than current power. They might not.)

    Here’s the specific native numbers for power as well as the steps to look up native numbers for any fields:
    • Download the FIT sdk: https://www.thisisant.com/resources/FIT
    • Open the profile spreadsheet
    • Switch to the Messages tab
    • Scroll to the Activity File Messages section
    • Look up field numbers and units in the appropriate subsection.
      • Summary fields - Subsection: session

        avg_power = 20 (units: watts)
        max_power = 21
      • Lap fields - Subsection: lap

        avg_power = 19
        max_power = 20
      • Activity graph fields - Subsection: record

        power = 7


    e.g. Create a field that’s equivalent to power in the activity graph:
    var powerField = createField("Power", fieldId, FitContributor.DATA_TYPE_UINT16,
    {:mesgType => Fit.MESG_TYPE_RECORD, :units => "W", :nativeNum => 7});
  • AWESOME!!! Promote this man to GURU Member :-)
  • No worries!

    Eh I'm just regurgitating info that's been passed down by other developers and users who tested my apps for me. I don't even use the Power recording features in any of my apps. It's them you should thank.

    Anyway, to avoid duplication of effort, you may wish to search for "virtual power" in the app store. I think there's already a few data fields that try to estimate running/cycling power without a power meter. At the very least you can see what papers/equations they referenced.
  • So I wrote my Data Field. It properly adds User Field "power" to the FIT file. I see the data in SportTracks and XERT. So I know it is there. But a graph in Garmin Connect does not show up for my User Field data. Is there anything special I need to do to see it? I've tried from a browser on my laptop, and from the Mobile version.
    https://apps.garmin.com/en-US/apps/fc901968-4705-4ed9-9c6a-6839c9efa2b5

  • You need to properly define fitContributions in your application XML:
    https://developer.garmin.com/index.p...he-full-circle

    Garmin Connect uses the information in fitContributions for label, units, graph color, etc. I think it's done this way so multiple languages can be supported, and also because things like graph color don't have a place in the FIT file itself.

    You can test this before uploading to the store by using monkeygraph (although it's a bit buggy). Monkeygraph takes the FIT file and the IQ file (which contains the app XML), and displays a graph like you'd see in GC.
  • FANTASTIC!!!! You rock FlowState!! Worked perfectly.
  • FlowState,

    I am using following options when I call createSession {..., :sport=>ActivityRecording.SPORT_TRAINING,
                        :subSport=>ActivityRecording.SUB_SPORT_STRENGTH_TRAINING}

    I presume that in this case the laps are actually sets and that I should look at

    set fields - Subsection: set for nativeNums

    even though the createField call uses :mesgType=>FC.MESG_TYPE_LAP

    I am thinking of the duration field (=0) and the weight field (=4)

    Does that sound right to you?

  • What happens if a real power is connected, this overwrites the real power data??

  • Could you find out how to add a weight training set to a session? If so, can you share the solution?

  • Some third party sites:
    Interpret some nativeNum developer fields as "native", which is what developers would prefer (obviously).

    It’s a great news, but whether there is any direct tool or an indirect solution (import and export) which can finally place the developer’s power field into the native power field? 

    So from one with NativeNum to ID=7?

    So far I found no solution and therefore cannot make any ex-post calculations with running power in the sw I use, which is the rusty Sporttracks 3.0 (PC version).

    I wondered whether all these calculations should be done within a ciq datafield, but a “peak power over 60 minutes” et al being calculated realtime  would kill any Garmin watch. :-)

    So I am looking for a solution - even if it is a sort of manual one, but a fast one - to squeeze Styrd power into native power.