1# Copyright (c) 1999-2000 Jo�o Pedro Gon�alves <joaop@sl.pt>. 2#All rights reserved. This program is free software; 3#you can redistribute it and/or modify it under the same terms as Perl itself. 4 5package GPS::NMEA; 6 7use GPS::Base (); 8use GPS::Serial (); 9use GPS::NMEA::Handler (); 10 11use strict; 12use Carp; 13use vars qw($VERSION @ISA); 14 15require Exporter; 16 17@ISA = qw(GPS::Base GPS::Serial GPS::NMEA::Handler); 18 19$VERSION = 1.12; 20 21use FileHandle; 22 23sub new { 24 my $class = shift; 25 my %param = @_; 26 $param{'Protocol'} ||= 'NMEA'; 27 28 my $self = $class->SUPER::common_new(%param); 29 bless $self, $class; 30 31 $self; 32} 33 34sub parse { 35 my $self = shift; 36 my $line = $self->_readline; #from GPS::Serial 37 while () { 38 my $short_cmd = $self->parse_line($line); 39 return $short_cmd if defined $short_cmd; 40 } 41} 42 43sub parse_line { 44 my($self, $line) = @_; 45 my ($csum,$cmd,$short_cmd); 46 47 #remove trailing chars 48 chomp($line);$line =~ s/\r//g; 49 50 #Test checksum 51 if ($line =~ s/\*(\w\w)$//) { 52 $csum = $1; 53 #XXX del? return $self->parse(@_) unless $csum eq $self->checksum($line); 54 return undef unless $csum eq $self->checksum($line); 55 } 56 57 $cmd = (split ',',$line)[0]; 58 ($short_cmd = $cmd) =~ s/^\$//; 59 60 print "COMMAND: $short_cmd ($line)\n" if $self->verbose; 61 if ($self->can($short_cmd)) { 62 $self->$short_cmd($line); 63 } elsif ($self->verbose) { 64 print "Can't handle $short_cmd\n"; 65 } 66 $short_cmd; 67} 68 69 70sub get_position { 71 #($latsign,$lat,$lonsign,$lon) 72 my $self = shift; 73 74 until ($self->parse eq 'GPRMC') { 75 1; 76 } 77 ; #Recommended minimum specific 78 my $d = $self->{NMEADATA}; 79 return ($d->{lat_NS}, 80 $self->parse_ddmm_coords($d->{lat_ddmm}), 81 $d->{lon_EW}, 82 $self->parse_ddmm_coords($d->{lon_ddmm})); 83} 84 85sub get_altitude { 86 my $self = shift; 87 until ($self->parse eq 'PGRMZ') { 88 1; 89 } 90 ; #Altitude 91 my $d = $self->{NMEADATA}; 92 return ($d->{alt}/0.3048); #Metric 93} 94 95sub parse_ddmm_coords { 96 my $self = shift; 97 $_ = shift; 98 my $deg; 99 my ($dm,$sec) = split(/\./); 100 101 if (length($dm) == 4) { #Lat (ddmm) 102 $deg = substr($dm,0,2,''); 103 } elsif (length($dm) == 5) { #Lon (dddmm) 104 $deg = substr($dm,0,3,''); 105 106 } else { 107 carp "Invalid coords\n"; 108 } 109 110 $deg = sprintf("%d",$deg); 111 return "$deg.$dm$sec"; 112} 113 114 115 116sub nmea_data_dump { 117 #dumps data received 118 my $self = shift; 119 my $d = $self->{NMEADATA}; 120 print map {"$_ => $$d{$_}\n"} sort keys %{$self->{NMEADATA}}; 121} 122 123# Calculate the checksum 124# 125sub checksum { 126 my ($self,$line) = @_; 127 my $csum = 0; 128 $csum ^= unpack("C",(substr($line,$_,1))) for(1..length($line)-1); 129 130 print "Checksum: $csum\n" if $self->verbose; 131 return (sprintf("%2.2X",$csum)); 132} 133 134 135 1361; 137__END__ 138 139=head1 NAME 140 141GPS::NMEA - Perl interface to GPS equipment using the NMEA Protocol 142 143=head1 SYNOPSIS 144 145 use GPS::NMEA; 146 $gps = new GPS::NMEA( 'Port' => '/dev/ttyS0', 147 'Baud' => 9600, 148 ); 149 150 151=head1 DESCRIPTION 152 153GPS::NMEA allows the connection and use of of a GPS receiver in perl scripts. 154 155Note that latitudes and longitudes are in DMM format. 156 157=over 158 159=head1 GETTING STARTED 160 161 162=head1 KNOWN LIMITATIONS 163 164 165=head1 BUGS 166 167 168=head1 EXAMPLES 169 170Get the position periodically: 171 172 #!/usr/bin/perl 173 use GPS::NMEA; 174 175 my $gps = GPS::NMEA->new(Port => '/dev/cuaa0', # or COM5: or /dev/ttyS0 176 Baud => 4800); 177 while(1) { 178 my($ns,$lat,$ew,$lon) = $gps->get_position; 179 print "($ns,$lat,$ew,$lon)\n"; 180 } 181 182Get the internal NMEA dump: 183 184 #!/usr/bin/perl 185 use GPS::NMEA; 186 use Data::Dumper; 187 188 my $gps = GPS::NMEA->new(Port => '/dev/cuaa0', # or COM5: or /dev/ttyS0 189 Baud => 4800); 190 while(1) { 191 $gps->parse; 192 193 # Dump internal NMEA data: 194 $gps->nmea_data_dump; 195 196 # Alternative to look at the internal NMEA data: 197 require Data::Dumper; 198 print Data::Dumper->new([$gps->{NMEADATA}],[])->Indent(1)->Useqq(1)->Dump; 199 } 200 __END__ 201 202=head1 AUTHOR 203 204Joao Pedro B Gon�alves , joaop@iscsp.utl.pt 205 206=head1 SEE ALSO 207 208=cut 209