FItContributor field limit

Is the FitContributor field limit of 16 across all installed data fields imposed based on

1) the definition in the fitcontributor.xml file?

2) the first 16 createField() calls?  That is, one can have more than the limit defined in the xml file, but as long as <=16 are not created, the limit is not hit?

3) the order of calls to setData() ?   That is, one can create more than the limit of 16, but as long as <=16 are written to, the limit is not hit?

  • 1) the definition in the fitcontributor.xml file?

    I doubt it, since that definition is apparently only used by the Connect app/site to help display recorded FIT data.

    2) the first 16 createField() calls?  That is, one can have more than the limit defined in the xml file, but as long as <=16 are not created, the limit is not hit?

    3) the order of calls to setData() ?   That is, one can create more than the limit of 16, but as long as <=16 are written to, the limit is not hit?

    Does it really matter which one it is? Let's say the number of createField() calls your app will make is X, and the number of fields setData() will be called for is Y, where Y <= X.

    ideally your app has to handle the worst-case scenario, so it seems that that you'd want to handle the case where Y = X.

    If you're worried about hitting the limit, seems that the best strategy is to limit the number of calls to createField(). After all, why create more fields than you can safely write to? Why create a field that you don't intend to write to? Unless you have a very esoteric use case where you must create X fields, but you are absolutely sure you will never write all of them.

    If you're curious about what the answer actually is, you could probably test it yourself.

    EDIT: If I had to guess, I'd say 2 tho.

  • If you're worried about hitting the limit, seems that the best strategy is to limit the number of calls to createField(). After all, why create more fields than you can safely write to? Why create a field that you don't intend to write to? Unless you have a very esoteric use case where you must create X fields, but you are absolutely sure you will never write all of them.

    In my data field, I would like to save the output in the FIT file either in min/km or in min/mile, depending on "System.UnitsSystem".

    To do this, I have created two "fitField" entries in the xml file, but only use one of them, depending on "System.UnitsSystem".

    I could not think of any other solution.

  • Ah, that's a good example. But do you actually call createField() twice? I can only see that happening if your data field would support switching units on the fly.

  • Perhaps I have described it badly.

    I have defined the following in fitcontributions.xml:

    <resources>
        <fitContributions>

        <!-- MESG_TYPE_SESSION : The message type for session messages.  -->

            <fitField id="0"
            displayInChart="false"
            displayInActivityLaps="false"
            displayInActivitySummary="true"

            sortOrder = "0"
            dataLabel="@Strings.summaryRunPace"
            unitLabel="@Strings.summaryPaceUnitMinPerKm"
            />

            <fitField id="10"
            displayInChart="false"
            displayInActivityLaps="false"
            displayInActivitySummary="true"

            sortOrder = "10"
            dataLabel="@Strings.summaryRunPace"
            unitLabel="@Strings.summaryPaceUnitMinPerMile"
            />
     ...
     
         </fitContributions>
    </resources>

    I then call the following in my program code:

    // Field ID from resources.
        const FIT_SUM_RUN_PACE_METRIC_FIELD_ID  =  0;
        const FIT_SUM_RUN_PACE_STATUTE_FIELD_ID = 10;

    ...
     // createField:
          /* Summary */

            var field_id_run = FIT_SUM_RUN_PACE_METRIC_FIELD_ID;
            var field_units = "min/km";

            if (self._paceUnits != System.UNIT_METRIC) {
              field_id_run = FIT_SUM_RUN_PACE_STATUTE_FIELD_ID;
              field_units = "min/mi";
            }
            
            self._fitSumRunPaceField = createField(
              "Run Pace",
              field_id_run,
              FitContributor.DATA_TYPE_STRING,
              { :count => FIT_SUM_RUN_PACE_STATUTE_FIELD_COUNT,
                :mesgType => FitContributor.MESG_TYPE_SESSION,
                :units => field_units}
            );

    ...
     // setData:
     
          var mySettings = System.getDeviceSettings();
          self._paceUnits = mySettings.paceUnits;
          
          if (self._paceUnits == System.UNIT_STATUTE) {
              pace = Convert.Pace.minPerKm2MinPerMile(pace);
          }
          
          dataStringPace = FormatString.Time.timeInSec2MinAndSec(pace as Float);

          self._fitSumRunPaceField.setData(dataStringPace);

    ...



    This means that in my program I create either the fitField=0 or the fitField=10 (createField) and write data only to this fitField (setData).

    So I have defined two fields in fitcontributions.xml, but only use one of them in my program.

  • Seems like a good solution. So now just define 15 other fields, create all the 15 others, and this one as number 16. If it works then the number of the fields in the xml (17) doesn't matter. If it doesn't work (even though there are only 16 fields created) then the number in the xml matters.

    However the real problem is that you'll get strange errors in ERA that you can't do anything about, and the only reason they happen is that some user added some other datafields to the activity next to your datafield, and them together use more that the 16-X (where X is the number of fields in your datafield) So knowing this I don't know if anything matters...

  • Perhaps I have described it badly.

    No I understood what you meant, but:

    - there was always the unlikely possibility that your app was written to support changing units on the fly. (I doubted it since the user probably wouldn't want to see partial graphs populated if they switched units. Alternatively if you always created 2 fields, you could've always written 2, but that isn't what you implied)

    - I was trying to make a point that I don't think the definitions in the XML file count against the limit, because I don't see what runtime resource could be possibly be consumed if you define more fields than you actually create.

  • The field stuff in the xml for fitcontrib is used to generate the json file that's contained in the iq file when you export an app.  It's not used at all in the prg file.  That's why when you use monkeygraph, you need to pass it the iq file - so it has access to the json for displaying the data

  • Why create a field that you don't intend to write to?

    The situation is that I intend to write to a field, but during the activity, conditions may not be met that allows measurement of the target metric, and thus no data is written.  I guess with a bit more logic that case can be accommodated to avoid creating the field until one has data to be written.

  • Why create a field that you don't intend to write to?

    The situation is that I intend to write to a field, but during the activity, conditions may not be met that allows measurement of the target metric, and thus no data is written.  I guess with a bit more logic that case can be accommodated to avoid creating the field until one has data to be written.

    Unfortunately that won't work, because createField() will fail past a certain point of the data field app "lifecycle" (believe me, I've tried.) If I recall correctly, calling createField() in DataField.initialize() works (for example), but not in compute() (as another example).

    Thanks for clarifying your use case (I was just curious). I think my point still stands that your app would need to handle the worst case scenario. Without knowing anything else about your app, I would guess that the worst case scenario would consist of writing to exactly as many fields as you create (unless you have some constraint / logic that says otherwise).

    Anyway, I still think the thing that counts against the limit is mostly likely 2, the number of calls to createField(). Each call immediately reserves a massive amount of memory in my experience. I'm fairly sure it's createField() itself that causes the memory allocation, not the first call to setData().