Read Serial array then plot it

I found one issue while parsing the complete file

$GPGSV,3,1,12,08,03,299,,10,61,322,34,12,11,114,21,15,16,070,*73
             | sat 1    | sat 2      | sat 3      | sat 4   |

Satellite 4 seems to be missing a field; however the checksum is correct. A little research shows that the split method seems to throw away that last field if it’s empty. The fix is an additional parameter for the split method.

Revised LineParser class below

//////////////////////////////////////////////////////////
// class for line parser
//////////////////////////////////////////////////////////
class LineParser
{
  String msgId = "";
  int numMessages = -1;
  int msgNumber = -1;
  int numSatellites = -1;
  ArrayList<SatelliteData> satData = new ArrayList<SatelliteData>();

  LineParser(String dataX)
    throws LineparserException
  {
    //println("original data = '" + dataX + "'");

    // throw away the start marker
    dataX = dataX.substring(1);

    // split in '*' to seperate actural data and checksum
    String[] data_cs = dataX.split("\\*");
    // we expect two strings (actual data and checksum)
    if (data_cs.length != 2)
    {
      throw new LineparserException("Could not determine checksum in '" + dataX + "'");
    }

    // calculate the checksum
    int cs = Integer.parseInt(data_cs[1], 16);
    for (int cnt = 0; cnt < data_cs[0].length(); cnt++)
    {
      cs ^= data_cs[0].charAt(cnt);
    }

    // the result of the checksum calculation should be zero
    if (cs != 0)
    {
      throw new LineparserException("Checksum error in '" + dataX + "'");
    }


    // bug fix; when a line ends with a comma (before the end marker), java does not consider it a filed
    // see e.g. https://stackoverflow.com/questions/13939675/java-string-split-i-want-it-to-include-the-empty-strings-at-the-end
    //String[] fields = data_cs[0].split(",");
    String[] fields = data_cs[0].split(",", -1);
    //printArray(fields);
    
    // check number of fields; needs to be multiple of 4
    if (fields.length % 4 != 0)
    {
      throw new LineparserException("Field count error in '" + dataX + "'");
      //return;
    }


    msgId = fields[0];
    numMessages = Integer.parseInt(fields[1]);
    msgNumber = Integer.parseInt(fields[2]);
    numSatellites = Integer.parseInt(fields[3]);

    // process the remaining fields
    for (int fCnt = 4; fCnt < fields.length; fCnt++)
    {

      SatelliteData sd = new SatelliteData(msgId, fields[fCnt]);
      //println(sd.satelliteNumber);
      //println("adding '" + fields[fCnt + 1] + "', '" + fields[fCnt + 2] + "', '" + fields[fCnt + 3] + "'");
      sd.addDetails(fields[fCnt + 1], fields[fCnt + 2], fields[fCnt + 3]);
      satData.add(sd);
      // only add 3; for-loop will add one more
      fCnt += 3;
      if (fCnt + 1 == fields.length)
      {
        //println("no more data in received data");
      } //
      else
      {
        //println("next field will be '" + fields[fCnt + 1] + "'");
      }
    }
  }

  void print()
  {
    println("msgId = '" + msgId + "'");
    println("numMessages = " + str(numMessages));
    println("msgNumber = " + str(msgNumber));
    println("numSatellites = " + str(numSatellites));

    for (int sdCnt = 0; sdCnt < satData.size(); sdCnt++)
    {
      satData.get(sdCnt).print();
    }
  }
}

As additional check, the code now also checks if the number of fields is a multiple of 4 (there are 4 header fields and 4 fields per satellite) and throws an exception if not.

Regarding printing the exception. If you’re printing all the data, you might loose part of the exception that is printed with e.printStackTrace(); In my main file I’ve added a delay(1000) before the e.printStackTrace() to prevent that.

1 Like