//ZylUdpGPSReceiver
//Copyright by Zyl Soft 2003 - 2006

unit ZylUdpGPSReceiver;

{$I IdCompilerDefines.inc}

{$C-}
interface

uses
   ZylCustomGPSReceiver, SysUtils, Windows, Classes, Math
   , IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer, IdSocketHandle
   {$ifndef CPPB5}
   , Dialogs, Forms, Controls
   {$endif}
   {$ifdef DELPHI6UP}
   , DateUtils
   {$endif};

type
  TConnectEvent = procedure(Sender: TObject; Port: Integer) of object;

  //Receiver class
  TZylUdpGPSReceiver = class(TZylCustomGPSReceiver)
  private
    { Private declarations }
    FPort: Integer;

    FSocket: TIdUDPServer;

    FOnConnect: TConnectEvent;
    FOnDisconnect: TConnectEvent;

    procedure SetPortA(Value: Integer);

    procedure ServerSocketUDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
  protected
    { Protected declarations }

  public
    { Public declarations }

    //constructor
    constructor Create(AOwner: TComponent);override;
    //destructor
    destructor Destroy();override;

    //starts communication
    procedure Open();
    //stops communication
    procedure Close();
  published
    { Published declarations }
    property Port: Integer read FPort write SetPortA default 10000;

    property ForceCheckSum;
    {$ifndef CPPB5}
    property NMEALog;
    {$endif}
    property Commands;

    property OnConnect: TConnectEvent read FOnConnect write FOnConnect;
    property OnDisconnect: TConnectEvent read FOnDisconnect write FOnDisconnect;
    //fires when new data was received
    property OnReceive;
    property OnLatitudeChange;
    property OnLongitudeChange;
    property OnAltitudeChange;
    property OnSpeedChange;
    property OnHeadingChange;
    property OnPosition2DChange;
    property OnPosition3DChange;
    property OnSatelliteReceive;
    property OnSatellitesReceive;
    property OnArrival;    
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Zyl Soft', [TZylUdpGPSReceiver]);
end;

{ TZylUdpGPSReceiver }

constructor TZylUdpGPSReceiver.Create(AOwner: TComponent);
begin
  inherited;

  FPort := 10000;

  FOnConnect := nil;
  FOnDisconnect := nil;

  FSocket := TIdUDPServer.Create(Self);
  FSocket.DefaultPort := FPort;
  FSocket.OnUDPRead := ServerSocketUDPRead;
end;

procedure TZylUdpGPSReceiver.SetPortA(Value: Integer);
begin
  try
    if FPort <> Value then
    begin
      FPort := Value;
      if FSocket.Active then
      begin
        Self.Open;
      end;
    end;
  except
    raise Exception.Create('Invalid port ' + IntToStr(Value) + '.');
  end;
end;

procedure TZylUdpGPSReceiver.Open();
begin
  Self.Close;

  FSocket.DefaultPort := FPort;
  FSocket.Active := True;

  if Assigned(FOnConnect) and FSocket.Active then
    FOnConnect(Self, FPort);
end;

procedure TZylUdpGPSReceiver.Close();
begin
  if FSocket.Active then
  begin
    if Assigned(FOnDisconnect) then
      FOnDisconnect(Self, FPort);
    FSocket.Active := False;
  end;
end;

destructor TZylUdpGPSReceiver.Destroy;
begin
  if FSocket.Active then
  begin
    FSocket.Active := False;
    FSocket.Free;
    FSocket := nil;
  end;
  inherited;
end;

procedure TZylUdpGPSReceiver.ServerSocketUDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
  strPacket: String;
begin
  SetLength(strPacket, AData.Size);
  AData.ReadBuffer(strPacket[1], Length(strPacket));
  FeedGPSReceiver(strPacket);
end;

end.


