Objective-C Wrapper generate broken header when include long message

I created FIT file include long product name and long descriptor. but, that FIT file fails to decode by FitCSVTool.jar.

I checked FIT file, data size in header is wrong. It was 256bytes less.

Apparently there is a problem in FitMesg class.

FitMesg returns message size on wirte message. Message size's type is FIT_UINT8. If message size is 256bytes or more, the correct size will not be returned.

Any help with a workaround would be appreciated.

Sample project

https://github.com/rseki-sonix/fit-ios-broken-header/blob/master/exampleios/ActivityExample.mm#L155-L160

Sample file(generated by sample project)

broken_header.fit.zip

  • Originally a message could not be greater than 255 bytes. That had less to do with the FIT Protocol and more to do with the number of places in the SDKs that were using a UINT8 to track the message size. This was changed in all of the SDKs, except the Objective-C SDK. Probably an oversight at the time. This is what is causing the issue in the example code that you provided. BTW, fields still need to be <=255 bytes since that is part of the FIT Protocol and changing that would break things. 

    Updating the Objective-C SDK is not something we are going to prioritize at this time, but I can give you a few work arounds.

    1. Keep your message sizes below 256 bytes. Messages with strings are probably the only ones you need to watch out for. Shorten the string in your example code by four characters and the file is not corrupted. The size of the non-string fields should be known ahead of time, so you will know how many bytes are available for the strings. You can use that information to trim the strings. Don't forget to include the null terminator in your calculations.

    2. Use the C++ SDK. The Objective-C SDK is really Objective-C++ so you are already mixing Objective-C and C++ in your project; the message classes are all C++. To do this, add all of the source files from the C++ SDK to your project. The SDK comes with a few C++ examples to show you how to use the encoder.

    3. This next one comes with an at your own risk warning. In the FitMesg message class change the two write methods to return a UINT16, and in the the second write method change the local mesgSize variable to be a UINT16. That seems to be the bare minimum to hack a solution. It worked for me, once, with your example code, but without proper testing it is not something that we would release or support. You would need to recompile the library or add all of the source files (hpp, cpp, h, and mm) to your project. I would put this in the try it for fun category.

  • Hi, Ben.

    Thank you for your reply and advice.

    I decided to fix the Objective-C wrapper.

    The modifications I made are as follows. It works fine in the sample project and my project.

    cpp/FitMesg.h

    #include "fit_mesg_definition.hpp"
     
    @interface FitMesg : NSObject
    // - (FIT_UINT8) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg;
    // - (FIT_UINT8) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg withDef:(const fit::MesgDefinition *)mesgDef;
    - (FIT_UINT16) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg;
    - (FIT_UINT16) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg withDef:(const fit::MesgDefinition *)mesgDef;
    @end
    
    #endif /* FIT_MESG_H */

    cpp/FitMesg.mm

    @implementation FitMesg
    
    // - (FIT_UINT8) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg
    - (FIT_UINT16) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg
    {
        return [self Write:file forMesg:mesg withDef:FIT_NULL];
    }
    
    // - (FIT_UINT8) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg withDef:(const fit::MesgDefinition *)mesgDef
    - (FIT_UINT16) Write:(FILE *) file forMesg:(const fit::Mesg *)mesg withDef:(const fit::MesgDefinition *)mesgDef
    {
        fit::MesgDefinition mesgDefOnNull;
        // FIT_UINT8 mesgSize = 1;
        FIT_UINT16 mesgSize = 1;
         FIT_UINT8 fieldSize = 0;
         FIT_UINT8 byte;