NMEAfields -- read captured NMEA data strings and return the data fields as part of a structure.
Make an interpretor with new(), and use it to generate data objects.
use NMEAfields; my $I = NMEAfields->new(); # one one interpreter needed my $line; my $dataP;
while($line = <STDIN>){
$dataP = $I->Interp($line); # get a data object
# do something with the $dataP
}
These classes and methods are used to create a common interface to NMEA data streams, such as from GPS, Depth sounders, Roll-Pitch-Heave sensors, navigation systems, etc. In this first edition, only GGA and DPT strings are interpreted. As I have time, I (or others) can add what they find.
The interpreter separates the instrument code from the data type and
interprets based on the data type. For example, $IIGGA and $GPGGA are
interpreted in the same way.
This module does NOT do sum checks on the data streams.
The data objects returned by Interp are of their own class, NMEAdata, with their own methods.
For conversion from Lat/Long to UTM, the NMEAdata methods use Geo::Coordinates::UTM.
For conversion from GPS time to UNIX time notation (different epoch), the NMEAdata methods use Time::Local.
The following device codes (first two letters of the string) are understood by NMEAfields:
The following element codes (third, fourth, and fifth letters of the string) are understood by NMEAfields:
COG => 'course over ground',
BOD => 'Course waypoint to waypoint',
BWC => 'bearing from fix to waypoint',
BWW => 'Course waypoint to waypoint',
DBS => 'depth below surface',
DBT => 'depth below transducer',
DPT => 'depth',
GLL => 'geographic Position - Latitude/Longitude',
GSA => 'GPS DOP and active satellites',
GSV => 'satellites in view',
HDG => 'heading magnetic',
HDM => 'heading magnetic',
HDT => 'heading true',
MTW => 'Water temperature',
RMA => 'Recommended Minimum Specific Loran-C Data',
RMB => 'Recommended Minimum Navigation Information',
RMC => 'Recommended Minimum Specific GNSS Data',
RMZ => 'Altitude (Garmin)',
RME => 'Estimated Error Information (Garmin)',
RMF => 'GPS Fix Data (Garmin)',
RTE => 'Routes RTE - Routes',
VHW => 'Velocity through water',
VLW => 'Distance traveled through water',
VWR => 'Relative velocity of wind',
VTG => 'track made good and ground speed',
WPL => 'waypoint position',
XTE => 'cross track error',
ZDE => 'date and time',
ZDA => 'date and time',
NMEAfields Methods
NMEAfields->new($GPSmaker)Creates a new interpreter for NMEA streams. The NMEA strings are not actually proprietary information of the equipment manufacturers, and so vary from one manufacturer to another. Many are not publicly documented.
Takes an option argument for the GPS manufacturer. By default, GARMIN
NMEAfields->Interp($string)This method takes the NMEA string as its argument. It returns a new
object of the class NMEAdata, which has its own set of methods.
Interp will strip leading and trailing whitespace before parsing
the string.
If the argument string is empty or can not be interpreted as NMEA, Interp
will return under.
It takes a string as its argument
NMEAdata Methods
NMEAdata->RawRaw returns a subset of the total NMEAdata structure.
These fields are not particularly useful to outside programs.
The main reason for the NMEAfields:: module is to produce data
that doesn t require any interpretation outside of the module.
The subset has any of the available following fields:
RawFixTime
The general format of time is hhmmss.sss
RawFixDate
The general format of time is ddmmyy
RawLat
The general format is ddmm.mmmm
NorthSouth
A character N or S designating hemisphere of latitude
RawLong
The general format is ddmm.mmmm
EastWest
A character E or W designating hemisphere of longitude
COG
Course over ground (True if not otherwise specified by TrueMagn
TrueMagn
A character T or M designating type of bearing/course. Assume
True (rather than Magnetic) if this field is missing.
SOG
Speed over ground. Assume knots if not specified by a SOGunit
SOGunit
A character N (knots), K (kilometers per hour), M (miles per hour).
Assume knots if this field is missing.
dptDepthFeet
Depth below transducer in feet.
dptDepthMeters
Depth below transducer in meters.
dptDepthFathoms
Depth below transducer in fathoms.
These values are in the NMEA native format which is usually readable, but often a munged up version of the data.
NMEAdata->CookedCooked returns a subset of the total NMEAdata structure.
These fields are the more useful versions of the data that comes
from the raw fields. But, it doesn t stop here, there are many
other methods that give specific formats and transformations of the
data. (See Below.)
The subset has any of the available following fields:
FixTimeH
The hour
FixTimeM
The minute
FixTimeS
The second
FixDateD
The day of the month
FixDateM
The month of the year (January = 1)
FixDateY
The year (only the last two digits)
LatDecDeg
The latitude in signed decimal degrees. Negative latitudes are b<S>outh of the equator.
LongDecDeg
The longitude in signed decimal degrees. Negative longitudes are b<W>est of the prime meridian.
COG
Course over ground (True if not otherwise specified by TrueMagn
(Unchanged from the Raw method.)
TrueMagn
A character T or M designating type of bearing/course. Assume
True (rather than Magnetic) if this field is missing.
(Unchanged from the Raw method.)
SOG
Speed over ground. Assume knots if not specified by a SOGunit
(Unchanged from the Raw method.)
SOGunit
A character N (knots), K (kilometers per hour), M (miles per hour).
Assume knots if this field is missing.
(Unchanged from the Raw method.)
dptDepthFeet
Depth below transducer in feet.
(Unchanged from the Raw method.)
dptDepthMeters
Depth below transducer in meters.
(Unchanged from the Raw method.)
dptDepthFathoms
Depth below transducer in fathoms.
(Unchanged from the Raw method.)
These values are in the NMEA native format which is usually readable, but often a munged up version of the data.
NMEAdata->Data(fieldList)
Returns the list of data values corresponding to the fields
in the fieldlist. A single field name returns a single value
provided that that data exists.
=cutsub Data { my $self = shift; my @fieldlist = @_; my @results = ();
for(@fieldlist){
push(@results,$self->{$_});
}
return @results;
}
################### Special Data and Formats ##########################
############### Checksum
=head3 NMEAdata->Checksum()
Returns 1 (True) if the calculated checksum equals the transmitted (embedded)
checksum. Returns 0 (False) if they do not agree. If FALSE, then an error
is placed in the Error attribute. See NMEA-<gt>Error.
=cut
sub Checksum { my $self = shift; if( $self->{_CKS_} eq $self->{_calcCKS_}) { return 1; } else { $self->SetError( ``Checksum error: calcualte=$self->{_calcCKS_} provided=$self->{_CKS_}'' ); return 0; } }
############## SetError
=head3 NMEAdata->SetError(string)
Sets the Error attribute to string.
=cut
sub SetError { my $self = shift; my $error = shift; $self->{_ERROR_} = ``!Error: \t$error\n!String:\t $self->{string}\n''; }
NMEAdata->ClrError(string)
Clears the Error attribute to undef.
=cutsub ClrError { my $self = shift; $self->{_ERROR_} = undef; }
NMEAdata->Error(string)
Clears the Error attribute to undef and
returns any error string that it was
set to.
=cutsub Error { my $self = shift; my $errorStr = $self->{_ERROR_}; $self->ClrError(); return $errorStr; }
sub DeviceCode { my $self = shift; return $self->{_DEVICE_}; }
sub Device { my $self = shift; return (defined $devices{$self->{_DEVICE_}}) ? $devices{$self->{_DEVICE_}} : ''; }
sub ElementCode { my $self = shift; return $self->{_ELEMENT_}; }
sub Element { my $self = shift; return $elements{$self->{_ELEMENT_}}; }
################ PositionStr sub PositionStr { # just a data formatting method my $self = shift;
return sprintf("%08.5f, %08.5f",
$self->{LatDecDeg},
$self->{LongDecDeg});
}
################ TimeStr
NMEAdata->TimeStrReturns a zero padded string of the format hh:mm:ss MM/DD/YY for
the time of the fix
NMEAdata->LL2UTMReturns the three element list ($UTMzone,$Easting,$Northing). The
values of easting and northing are in meters. The UTM projection facilitates
plotting because it represents the surface of the planet as a rectiliniar grid.
The projection is based on the WGS84 Ellipsoid, the standard for most GPS
fixes.
Uses the module Geo::Coordinates::UTM
NMEAdata->ZoneReturns the UTM Zone. For a better understand of UTM zones see
Geo::Coordinates::UTM
NMEAdata->EastingReturns the easting in meters. See LL2UTM for information
on zones, easting, and northing.
NMEAdata->NorthingReturns the easting in meters. See LL2UTM for information
on zones, easting, and northing.
NMEAdata->UNIXtimeReturns the long-integer/float value of the fixtime, using the UNIX style epoch of January 1, 1970. This is a convenient value for timestamping. If the device returns an fractional second in its time string, the floating point version is returned.
This uses the module Time::Local
Ben Smith, Captain of the Sailing Vessel Mother of Perl, in the Caribbean Seas =head1 BUGS
To be determined
This program is free software, You may copy or redistribute it under the same terms as Perl itself.