GetRiderPosition() Throws Specified cast is not valid.

As I understand it, eMesg.GetRiderPosition() is supposed to return RiderPositionType  enum.

When I call the function 

 EventMesg eMesg = (EventMesg)e.mesg;

RiderPositionType? positiontype= eMesg.GetRiderPosition();

I'm getting the error

'Specified cast is not valid.'
This exception was originally thrown at this call stack:
Dynastream.Fit.EventMesg.GetRiderPosition() in EventMesg.cs
Garmin21._126ConsoleApp.FitImport.FITExtract.MesgBroadcaster_EventMesgEvent(object, Dynastream.Fit.MesgEventArgs) in FITExtract.cs
Dynastream.Fit.MesgBroadcaster.OnMesg(object, Dynastream.Fit.MesgEventArgs) in MesgBroadcaster.cs
Dynastream.Fit.Decode.RaiseMesgEvent(Dynastream.Fit.Mesg) in Decode.cs
Dynastream.Fit.Decode.DecodeNextMessage(System.IO.Stream) in Decode.cs
Dynastream.Fit.Decode.Read(System.IO.Stream, Dynastream.Fit.DecodeMode) in Decode.cs
Dynastream.Fit.Decode.Read(System.IO.Stream) in Decode.cs
Garmin21._126ConsoleApp.FitImport.FITExtract.DecodeFitFile() in FITExtract.cs

Any help would be appreciated.

  • The rider position field in the Event mesg is a subfield of the Data field. Which subfield is valid is based off of the value of another field. For the Data field in the Event mesg, most subfields are keyed off of the Event field. Take a look at Profile.xlsx to see the definitions of the subfields in the Event mesg.

    Try this, before calling event.GetRiderPosition() make sure that event.GetEvent() == Event.RiderPositionChange

    Although, GetRiderPosition() should return null if the event is not Event.RiderPositionChange. So it might be that there is an incorrect rider position value stored in the file. If you look at the RiderPositionType enum, the raw values are 0, 1, 2, and 3. If there is any other value in the file, the cast to the enum type is what is throwing the error.

    The GetRiderPosition() method is one line long

    return (RiderPositionType?)GetFieldValue(3, 0, DataSubfield.RiderPosition);

    https://github.com/garmin/fit-csharp-sdk/blob/main/Dynastream/Fit/Profile/Mesgs/EventMesg.cs#L662 

    You could try calling GetFieldValue() directly without the cast. 

    event.GetFieldValue(3, 0, DataSubfield.RiderPosition);

    If that works, then there is a rider position value in the file that is not in the RiderPosition enum.
    What device is the file from?

     

  • The FIT file is generated by the Edge 840. firmware 23.10

    The following code is in EventMesg.cs

    /// <summary>
    /// Retrieves the RiderPosition subfield
    /// Comment: Indicates the rider position value.</summary>
    /// <returns>Nullable RiderPositionType enum representing the RiderPosition subfield</returns>
    public RiderPositionType? GetRiderPosition()
    {
    return (RiderPositionType?)GetFieldValue(3, 0, DataSubfield.RiderPosition);

    }

    I have validated the results I am capturing with the https://www.fitfileviewer.com/ and FitToCSV-data.bat

    I am able to capture the Rider Position with the Data field in the case statement.

    My Code

    The delegate method is. This is not the full code.

     private void MesgBroadcaster_EventMesgEvent(object sender, MesgEventArgs e)
    {

          EventMesg eMesg = (EventMesg)e.mesg; 

          int eventid = Convert.ToInt32(eMesg.GetEvent());
          int eventtype= Convert.ToInt32( eMesg.GetEventType());

           //Rider position change Event  44
          if (eventid == (int)Event.RiderPositionChange)
          { 
              //Calling GetRiderPosition() causes an invalid cast error
              //RiderPositionType? positiontype= eMesg.GetRiderPosition();

       RiderPositionType rp = RiderPositionType.Invalid;
    foreach (Dynastream.Fit.Field field in eMesg.Fields)
    {
    Console.WriteLine($"{field.Name} {field.GetValue()}");
    log.Info("Rider position change event");
    log.Info($"{field.Name} {field.GetValue()}");

    switch (field.Name)
    {
    case "Timestamp":
    timestamp = Convert.ToInt64(field.GetValue());
    datetime = LocalDateTime.GetLocalTimeFromTimeStamp(field.GetValue());
    break;
    case "Data":
    if (Convert.ToInt32(field.GetValue()) == (int)RiderPositionType.Seated)
    {
    rp = RiderPositionType.Seated;
    } else if (Convert.ToInt32(field.GetValue()) == 1)
    {
    rp = RiderPositionType.Standing;
    }
    else if (Convert.ToInt32(field.GetValue()) == 2)
    {
    rp = RiderPositionType.TransitionToSeated;
    }
    else if (Convert.ToInt32(field.GetValue()) == 3)
    {
    rp = RiderPositionType.TransitionToStanding;
    }
    else //(Convert.ToInt32(field.GetValue()).ToString("X") == "0xFF")
    {
    rp = RiderPositionType.Invalid;
    }
    // position = (int)field.GetValue();
    break;
    case "EventType":
    marker = Convert.ToInt32(field.GetValue());
    break;
    }
    }
           }

    }