NMEA2000 icon indicating copy to clipboard operation
NMEA2000 copied to clipboard

ParseN2kPGN126992 data type error

Open lsoltero opened this issue 3 years ago • 5 comments

3540881 : Pri:3 PGN:126992 Source:2 Dest:255 Len:8 Data:ff,ff,ff,ff,ff,ff,ff,ff N2kSysDateTime(2): SID=255, Date=65535, time=-0.0001, Source=15

should be returning N2kDoubleNA for time...

SystemTime=N2kMsg.Get4ByteDouble(0.0001,Index);

should really be

SystemTime=N2kMsg.Get4ByteUDouble(0.0001,Index);

here is the current code showing the error.

//***************************************************************************** bool ParseN2kPGN126992(const tN2kMsg &N2kMsg, unsigned char &SID, uint16_t &SystemDate, double &SystemTime, tN2kTimeSource &TimeSource) { if (N2kMsg.PGN!=126992L) return false;

int Index=0;

SID=N2kMsg.GetByte(Index); TimeSource=(tN2kTimeSource)(N2kMsg.GetByte(Index) & 0x0f); SystemDate=N2kMsg.Get2ByteUInt(Index); SystemTime=N2kMsg.Get4ByteDouble(0.0001,Index);

return true; }

lsoltero avatar Jun 20 '21 18:06 lsoltero

--- a/src/N2kMessages.cpp
+++ b/src/N2kMessages.cpp
@@ -46,7 +46,7 @@ bool ParseN2kPGN126992(const tN2kMsg &N2kMsg, unsigned char &SID, uint16_t &Syst
   SID=N2kMsg.GetByte(Index);
   TimeSource=(tN2kTimeSource)(N2kMsg.GetByte(Index) & 0x0f);
   SystemDate=N2kMsg.Get2ByteUInt(Index);
-  SystemTime=N2kMsg.Get4ByteDouble(0.0001,Index);
+  SystemTime=N2kMsg.Get4ByteUDouble(0.0001,Index);
 
   return true;
 }

lsoltero avatar Jun 21 '21 00:06 lsoltero

Thanks. I'll update it to code.

ttlappalainen avatar Jun 21 '21 18:06 ttlappalainen

I think the issue might be with more than 126992. Although I don't have any live data for 129029 it looks from the code that it might have the same issue. Time is SET at a 4ByteUDouble but read as a 4ByteDouble. So... you might get a negative value instead of N2kDoubleNA if the data is not valid. Might be worth to do a search for all the SecondsSinceMidnight and update appropriately.

Here is the code for 129029 showing the same issue.

void SetN2kPGN129029(tN2kMsg &N2kMsg, unsigned char SID, uint16_t DaysSince1970, double SecondsSinceMidnight,
                     double Latitude, double Longitude, double Altitude,
                     tN2kGNSStype GNSStype, tN2kGNSSmethod GNSSmethod,
                     unsigned char nSatellites, double HDOP, double PDOP, double GeoidalSeparation,
                     unsigned char nReferenceStations, tN2kGNSStype ReferenceStationType, uint16_t ReferenceSationID,
                     double AgeOfCorrection
                     ) {


    N2kMsg.SetPGN(129029L);
    N2kMsg.Priority=3;
    N2kMsg.AddByte(SID);   
    N2kMsg.Add2ByteUInt(DaysSince1970);
    N2kMsg.Add4ByteUDouble(SecondsSinceMidnight,0.0001);
    N2kMsg.Add8ByteDouble(Latitude,1e-16);
    N2kMsg.Add8ByteDouble(Longitude,1e-16);  
    N2kMsg.Add8ByteDouble(Altitude,1e-6);
    N2kMsg.AddByte( (((unsigned char) GNSStype) & 0x0f) | (((unsigned char) GNSSmethod) & 0x0f)<<4 );
    N2kMsg.AddByte(1);  // Integrity 2 bit, reserved 6 bits
    N2kMsg.AddByte(nSatellites);
    N2kMsg.Add2ByteDouble(HDOP,0.01);
    N2kMsg.Add2ByteDouble(PDOP,0.01);
    N2kMsg.Add4ByteDouble(GeoidalSeparation,0.01);
    if (nReferenceStations!=0xff && nReferenceStations>0) {
      N2kMsg.AddByte(1); // Note that we have values for only one reference station, so pass only one values.
      N2kMsg.Add2ByteInt( (((int)ReferenceStationType) & 0x0f) | ReferenceSationID<<4 );
      N2kMsg.Add2ByteUDouble(AgeOfCorrection,0.01);
    } else N2kMsg.AddByte(nReferenceStations);
}
  
bool ParseN2kPGN129029(const tN2kMsg &N2kMsg, unsigned char &SID, uint16_t &DaysSince1970, double &SecondsSinceMidnight,
                     double &Latitude, double &Longitude, double &Altitude,
                     tN2kGNSStype &GNSStype, tN2kGNSSmethod &GNSSmethod,
                     uint8_t &nSatellites, double &HDOP, double &PDOP, double &GeoidalSeparation,
                     uint8_t &nReferenceStations, tN2kGNSStype &ReferenceStationType, uint16_t &ReferenceSationID,
                     double &AgeOfCorrection
                     ) {
  if (N2kMsg.PGN!=129029L) return false;
  int Index=0;
  unsigned char vb;
  int16_t vi;
    
  SID=N2kMsg.GetByte(Index);
  DaysSince1970=N2kMsg.Get2ByteUInt(Index);
  SecondsSinceMidnight=N2kMsg.Get4ByteDouble(0.0001,Index);
  Latitude=N2kMsg.Get8ByteDouble(1e-16,Index);
  Longitude=N2kMsg.Get8ByteDouble(1e-16,Index);
  Altitude=N2kMsg.Get8ByteDouble(1e-6,Index);                                                                                                                               
  vb=N2kMsg.GetByte(Index); GNSStype=(tN2kGNSStype)(vb & 0x0f); GNSSmethod=(tN2kGNSSmethod)((vb>>4) & 0x0f);
  vb=N2kMsg.GetByte(Index);  // Integrity 2 bit, reserved 6 bits
  nSatellites=N2kMsg.GetByte(Index);
  HDOP=N2kMsg.Get2ByteDouble(0.01,Index);
  PDOP=N2kMsg.Get2ByteDouble(0.01,Index);
  GeoidalSeparation=N2kMsg.Get4ByteDouble(0.01,Index);
  nReferenceStations=N2kMsg.GetByte(Index);
  if (nReferenceStations!=N2kUInt8NA && nReferenceStations>0) {
    // Note that we return real number of stations, but we only have variabes for one.
    vi=N2kMsg.Get2ByteUInt(Index); ReferenceStationType=(tN2kGNSStype)(vi & 0x0f); ReferenceSationID=(vi>>4);
    AgeOfCorrection=N2kMsg.Get2ByteUDouble(0.01,Index);
  }

  return true;

lsoltero avatar Jun 21 '21 20:06 lsoltero

might also look at 129033 same issue.

Canboat says that all time values are positive only so that should give extra confidence in the change.

    {"Time", BYTES(4), RES_TIME, false, "s", "Seconds since midnight"},

lsoltero avatar Jun 21 '21 21:06 lsoltero

I'll check them. The problem arises only, if some device provides NA value. In that case it will be handled wrong. There should not be negative values, since max. sec. since midnight is 86400 so the value will get max. 864 000 000, which is far less than 2 147 483 647.

ttlappalainen avatar Jun 22 '21 02:06 ttlappalainen