How to design a data field that records fit fields and plays well with other fields

Problem: developer creates a data field that works perfectly alone or with even some other CIQ data fields, but can crash for reasons caused by other developers' data fields, because of the limitations of number of fit fields per field type per activity or on the total number of bytes all the fields (per type) can have.

Unfortunately neither of the 2 errors I see in ERA (that according to my understanding are caused by either having more than 16 fit fields of the same type => System Error, or by having too many bytes of the fit fields' size alltogether => Out Of Memory Error) can be caught with try/catch :( 

I know this came up a few times in the past, and I know most developers think that Garmin should do something with this, but until that, what do you recommend to do? I could think of not very useful things like:

- ignore the System error, Out of memory error in ERA when it's from the function that creates the fit fields => crashes => bad user experience

- add some explanation about how other fields added to the same activity can cause my data field to crash => not the best user experience (most won't even read)

And then one that can be a bit more useful:

- add settings for each of my fit fields to be able to enable/disable them separately, and by that hopefully users with crash (and who read the description...) will be able to keep the more important fit fields while giving up on the less important => adds lot of code

  • Unless we can somehow prevent app crashes and predict app behavior, the whole FIT contribution feature should be considered experimental and never be enabled by default.

    Yeah, that’s why an app such as stryd zones, where FIT recording of several fields is a significant part of the app’s purpose and can’t be disabled, comes with a warning that other CIQ data fields should be uninstalled.

    It’s not a great situation

  • I added a UserSetting to my field to allow users to turn off the FIT fields. They don't read the users guide so they write to support who has to explain that their crash is likely doe to conflicts with other CIQ fields and to try to disable the FIT graphs using this option. Unfortunately that is the best we can do at this point. A try/catch would be nice, then we could bypass those creates that would otherwise crash our app. 

  • if you do it as an opt-in instead of opt-out there will be much less crashes (there are many users that never change a setting)

  • Yeah, and probably most users wouldn't even notice, 'cause they only look at the screen and have no clue about the data recorded

  • if you do it as an opt-in instead of opt-out there will be much less crashes (there are many users that never change a setting)

    Yeah I'm a strong believer in the practice of choosing default settings with the assumption that most users will never change a single setting.

    As far as this specific use case goes (data field that writes FIT fields), I think it depends on the app. For something like Stryd Zones, the primary purpose of the app is to write FIT fields to the activity, so for that app, it makes sense that not only is the default behaviour to write FIT fields, it's not possible to disable that behaviour either. That's why Stryd's "solution" to the problem is to tell users to uninstall all other CIQ fields. (I think I've seen similar advice for similar apps).

    For other CIQ data fields, it could very well be that the best course of action is to make writing FIT fields an optional setting which is disabled by default. (That's what I do for my niche data fields which can write data, as it's not their primary purpose.)

  • From the post header:


    > How to design a data field that records fit fields and plays well with other fields

    and

    > but can crash for reasons caused by other developers' data fields, because of the limitations of number of fit fields per field type per activity or on the total number of bytes all the fields (per type) can have.

    An approach I have tried is implementing https://github.com/mannyray/GarminBytePacking/. This monkey barrel library allows you to pack multiple fields into a single one which thus allows you to

    • reduce field count by compressing them into one single field (or at least fewer fields)
    • reduce potential bytes used as by using functions like `BytePacking.BinaryDataPair.binaryDataPairWithMaxBits` you can be very precise with how much space you need and don't

    An example of this approach is in https://github.com/mannyray/GarminBytePacking/?tab=readme-ov-file#watch-app-example where I pack 4 numbers into 64 bits of data and then convert them to a single double:

    var numbers = [523l, 8129l, 654321l, 9237l, 32l];
    var bitsRequired = [10, 13, 20, 14, 6];
    bitsRequired[2]+= 1;
    var packed = new BytePacking.BPLongPacked();
    for(var i=0; i<numbers.size(); i++){
        packed.addData(
            BytePacking.BinaryDataPair.binaryDataPairWithMaxBits(
                numbers[i],
                bitsRequired[i]
            )
        );
    }
    var byteArray = BytePacking.BPLong.longToByteArray(packed.getData());
    var dataDoubleEquivalent = BytePacking.BPDouble.byteArrayToDouble(byteArray);
    // now that we have converted the data to a double, we save it to FIT file
    session.recordData(dataDoubleEquivalent);

    We are packing 5 numbers into a single double fit field defined as 

    dataField = session.createField(
        "field",
        DATA_FIELD_ID,
        FitContributor.DATA_TYPE_DOUBLE,
        { :mesgType=>Fit.MESG_TYPE_RECORD }
    );

    The downside is that your fit fields will need to be post processed on a computer in order to be interpreted. There is example python code in the README on how to do that.

  • thanks for writing up this thread. I had all this try/catch logic built out in my new datafield but I guess it won't work because the errors can't be caught haha damn.