File Coverage

blib/lib/GPS/NMEA.pm
Criterion Covered Total %
statement 64 76 84.2
branch 9 18 50.0
condition 1 2 50.0
subroutine 13 15 86.6
pod 0 8 0.0
total 87 119 73.1


line stmt bran cond sub pod time code
1             # Copyright (c) 1999-2000 João Pedro Gonçalves .
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              
5             package GPS::NMEA;
6              
7 2     2   3706 use GPS::Base ();
  2         3  
  2         39  
8 2     2   650 use GPS::Serial ();
  2         6  
  2         39  
9 2     2   1270 use GPS::NMEA::Handler ();
  2         7  
  2         192  
10              
11 2     2   14 use strict;
  2         3  
  2         65  
12 2     2   10 use Carp;
  2         4  
  2         120  
13 2     2   10 use vars qw($VERSION @ISA);
  2         4  
  2         153  
14              
15             require Exporter;
16              
17             @ISA = qw(GPS::Base GPS::Serial GPS::NMEA::Handler);
18              
19             $VERSION = 1.12;
20              
21 2     2   31 use FileHandle;
  2         5  
  2         9  
22              
23             sub new {
24 3     3 0 2692 my $class = shift;
25 3         14 my %param = @_;
26 3   50     20 $param{'Protocol'} ||= 'NMEA';
27              
28 3         22 my $self = $class->SUPER::common_new(%param);
29 3         8 bless $self, $class;
30              
31 3         10 $self;
32             }
33              
34             sub parse {
35 14     14 0 30 my $self = shift;
36 14         67 my $line = $self->_readline; #from GPS::Serial
37 14         34 while () {
38 14         99 my $short_cmd = $self->parse_line($line);
39 14 50       106 return $short_cmd if defined $short_cmd;
40             }
41             }
42              
43             sub parse_line {
44 14     14 0 36 my($self, $line) = @_;
45 14         30 my ($csum,$cmd,$short_cmd);
46              
47             #remove trailing chars
48 14         55 chomp($line);$line =~ s/\r//g;
  14         78  
49              
50             #Test checksum
51 14 50       167 if ($line =~ s/\*(\w\w)$//) {
52 14         62 $csum = $1;
53             #XXX del? return $self->parse(@_) unless $csum eq $self->checksum($line);
54 14 50       70 return undef unless $csum eq $self->checksum($line);
55             }
56              
57 14         131 $cmd = (split ',',$line)[0];
58 14         88 ($short_cmd = $cmd) =~ s/^\$//;
59              
60 14 50       61 print "COMMAND: $short_cmd ($line)\n" if $self->verbose;
61 14 50       664 if ($self->can($short_cmd)) {
    0          
62 14         173 $self->$short_cmd($line);
63             } elsif ($self->verbose) {
64 0         0 print "Can't handle $short_cmd\n";
65             }
66 14         54 $short_cmd;
67             }
68              
69              
70             sub get_position {
71             #($latsign,$lat,$lonsign,$lon)
72 2     2 0 1502 my $self = shift;
73              
74 2         10 until ($self->parse eq 'GPRMC') {
75 12         69 1;
76             }
77             ; #Recommended minimum specific
78 2         7 my $d = $self->{NMEADATA};
79 2         17 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              
85             sub get_altitude {
86 0     0 0 0 my $self = shift;
87 0         0 until ($self->parse eq 'PGRMZ') {
88 0         0 1;
89             }
90             ; #Altitude
91 0         0 my $d = $self->{NMEADATA};
92 0         0 return ($d->{alt}/0.3048); #Metric
93             }
94              
95             sub parse_ddmm_coords {
96 4     4 0 8 my $self = shift;
97 4         8 $_ = shift;
98 4         12 my $deg;
99 4         16 my ($dm,$sec) = split(/\./);
100              
101 4 100       17 if (length($dm) == 4) { #Lat (ddmm)
    50          
102 2         9 $deg = substr($dm,0,2,'');
103             } elsif (length($dm) == 5) { #Lon (dddmm)
104 2         6 $deg = substr($dm,0,3,'');
105              
106             } else {
107 0         0 carp "Invalid coords\n";
108             }
109              
110 4         18 $deg = sprintf("%d",$deg);
111 4         28 return "$deg.$dm$sec";
112             }
113              
114              
115              
116             sub nmea_data_dump {
117             #dumps data received
118 0     0 0 0 my $self = shift;
119 0         0 my $d = $self->{NMEADATA};
120 0         0 print map {"$_ => $$d{$_}\n"} sort keys %{$self->{NMEADATA}};
  0         0  
  0         0  
121             }
122              
123             # Calculate the checksum
124             #
125             sub checksum {
126 14     14 0 107 my ($self,$line) = @_;
127 14         30 my $csum = 0;
128 14         440 $csum ^= unpack("C",(substr($line,$_,1))) for(1..length($line)-1);
129              
130 14 50       80 print "Checksum: $csum\n" if $self->verbose;
131 14         141 return (sprintf("%2.2X",$csum));
132             }
133              
134              
135              
136             1;
137             __END__