5

I'm looking for opensource Delphi NMEA parser of production grade.

It will be fine if it can meet critical mission requirement (I'm joking! I believe it's not attainable using a Win32 system).

So far, I have played around with basic interfacing of a wrist GPS (Garmin Foretrex 101) through serial port using basic windows API (NMEA 0183).

I have also explored an opensource VCL component to handle experimental serial communication with an aviation model GPS (Garmin Gpsmap 196).

Thanks.

menjaraz
  • 7,551
  • 4
  • 41
  • 81
  • 3
    Not open source, but still good, is the [NMEA GPS components from ZylSoft](http://www.zylsoft.com/). – LU RD Dec 14 '11 at 12:13
  • @ LU RD: Thanks, ZylSolf has written many outstanding components. – menjaraz Dec 14 '11 at 12:28
  • If you think something is not attainable then why are you asking for it? Clearly what you want is attainable there isn't a reason it can't be attainable. – Security Hound Jan 09 '12 at 16:01
  • @Ramhound: I've learnt from this [post](http://stackoverflow.com/q/7092955/744588) on SO that data may be corrupted during serial communication. Using Win32 based solution within a DIY aerial spraying guidance system is a nonsense for example. Nevertheless, there must room for improvement on the application level, but so far I don't know where to begin. – menjaraz Jan 09 '12 at 16:28

1 Answers1

4

I end up using TComPort and TComDataPacket from the open source TComPort package.


ComPort setting:

  object ComPort: TComPort
    BaudRate = br4800
    Port = 'COM1'
    Parity.Bits = prNone
    StopBits = sbTwoStopBits
    DataBits = dbEight
    Events = [evRxChar, evTxEmpty, evRxFlag, evRing, evBreak, evCTS, evDSR, evError, evRLSD, evRx80Full]
    FlowControl.OutCTSFlow = False
    FlowControl.OutDSRFlow = False
    FlowControl.ControlDTR = dtrDisable
    FlowControl.ControlRTS = rtsDisable
    FlowControl.XonXoffOut = False
    FlowControl.XonXoffIn = False
    SyncMethod = smWindowSync
    OnAfterOpen = ComPortAfterOpen
    OnAfterClose = ComPortAfterClose
    Left = 904
    Top = 192
  end

ComDataPacket settings:

  object ComDataPacket: TComDataPacket
    ComPort = ComPort
    StartString = '$'
    StopString = '*'
    OnPacket = ComDataPacketPacket
    Left = 808
    Top = 240
  end

Excerpt of type used

type
  // NMEA 0185's messages used
  TMsgGP = (
    msgGP,    // Unknown message
    msgGPGGA, // Global Positioning System Fix Data
    msgGPGLL, // Geographic position, Latitude and Longitude
    msgGPGSV, // Satellites in view
    msgGPRMA, // Recommended minimum specific GPS/Transit data Loran C
    msgGPRMC, // Recommended minimum specific GPS/Transit data
    msgGPZDA  // Date and time
    );

  // Satellite properties
  TSatellite = record
    Identification: ShortInt;
    Elevation: 0..90;
    Azimut: Smallint;
    SignLevel: Smallint;
  end;
  // Array of satellites referenced
  TSatellites = array[1..MAX_SATS] of TSatellite;

  // GPS status informations
  TGPSDatas = record
    Latitude: Double;
    Longitude: Double;
    HeightAboveSea: Double;
    Speed: Double;
    UTCTime: TDateTime;
    Valid: Boolean;
    NbrSats: Shortint;
    NbrSatsUsed: Shortint;
  end;

ComDataPacketPacket Event handler:

procedure TForm1.ComDataPacketPacket(Sender: TObject; const Str: string);
var
  Resultat: TStringList;
  MsgCorrect, TypeMsg: string;
  i: Integer;
begin
  Resultat := TStringList.Create;
  try

    // Split the message into different parts.
    MsgCorrect := AnsiReplaceStr('$'+Str, ',,', ' , , ');
    Resultat.Text := AnsiReplaceStr(LeftStr(MsgCorrect, Length(MsgCorrect) - 1), ',', #13#10);

    // Get the message type
    TypeMsg := AnsiMidStr(Resultat[0], 4, 3);

    case IndexMsgGP(TypeMsg) of
      msgGPGGA:
        begin
        end;
      msgGPGLL:
        begin
        end;
      msgGPGSV:
        begin
          // If there are satellites referenced in the frame
          if Resultat.Count < 4 then
            FGPSDatas.NbrSats := 0
          else
            FGPSDatas.NbrSats := StrToInteger(Resultat[3]);

          if Resultat[2] = '1' then
          begin
            FSatRef := 0;

            // Initiate satellites values
            for i := 1 to 12 do
              with FSatellites[i] do
              begin
                Identification := 0;
                Elevation := 0;
                Azimut := 0;
                SignLevel := 0;
              end;
          end;

          i := 4;

          // For each referenced satellites
          while (i + 4) <= (Resultat.Count) do
          begin
            with FSatellites[FSatRef + 1] do
            begin
              Identification := StrToInteger(Resultat[i]);
              Elevation := StrToInteger(Resultat[i + 1]);
              Azimut := StrToInteger(Resultat[i + 2]);
              if Resultat[i + 3] <> '' then
                SignLevel := StrToInteger(Resultat[i + 3])
              else
                SignLevel := 0;
            end;
            Inc(i, 4);
            Inc(FSatRef);
          end;
        end;
      msgGPRMA:
        begin
        end;
      msgGPRMC:
        begin
        end;
      msgGPZDA:
        begin
        end;
      else
    end;
  finally
    Resultat.Free;
  end;
end;

NMEA processing took place in the event handler.

menjaraz
  • 7,551
  • 4
  • 41
  • 81