line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Net::GPSD; |
2
|
1
|
|
|
1
|
|
643
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
30
|
|
3
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
28
|
|
4
|
1
|
|
|
1
|
|
786
|
use IO::Socket::INET; |
|
1
|
|
|
|
|
23857
|
|
|
1
|
|
|
|
|
8
|
|
5
|
1
|
|
|
1
|
|
1258
|
use Net::GPSD::Point; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
30
|
|
6
|
1
|
|
|
1
|
|
615
|
use Net::GPSD::Satellite; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1472
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION='0.39'; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 NAME |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
Net::GPSD - Provides an object client interface to the gpsd server daemon. |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 SYNOPSIS |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
use Net::GPSD; |
17
|
|
|
|
|
|
|
$obj=Net::GPSD->new; |
18
|
|
|
|
|
|
|
my $point=$obj->get; |
19
|
|
|
|
|
|
|
print $point->latlon. "\n"; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
or |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use Net::GPSD; |
24
|
|
|
|
|
|
|
$obj=Net::GPSD->new; |
25
|
|
|
|
|
|
|
$obj->subscribe(); |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=head1 DESCRIPTION |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
Note: This package supports the older version 2 protocol. It works for gpsd versions less than 3.00. However, for all versions of the gpsd deamon greater than 2.90 you should use the version 3 protocol supported by L. |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
Net::GPSD provides an object client interface to the gpsd server daemon. gpsd is an open source GPS deamon from http://gpsd.berlios.de/. |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
For example the get method returns a blessed hash reference like |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
{S=>[?|0|1|2], |
36
|
|
|
|
|
|
|
P=>[lat,lon]} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
Fortunately, there are various methods that hide this hash from the user. |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head1 CONSTRUCTOR |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head2 new |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
Returns a new Net::GPSD object. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
my $obj=Net::GPSD->new(host=>"localhost", port=>"2947"); |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=cut |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub new { |
51
|
1
|
|
|
1
|
1
|
107
|
my $this = shift(); |
52
|
1
|
|
33
|
|
|
12
|
my $class = ref($this) || $this; |
53
|
1
|
|
|
|
|
3
|
my $self = {}; |
54
|
1
|
|
|
|
|
4
|
bless $self, $class; |
55
|
1
|
|
|
|
|
4
|
$self->initialize(@_); |
56
|
1
|
|
|
|
|
3
|
return $self; |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head1 METHODS |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=head2 initialize |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=cut |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub initialize { |
66
|
1
|
|
|
1
|
1
|
2
|
my $self = shift(); |
67
|
1
|
|
|
|
|
4
|
my %param = @_; |
68
|
1
|
|
50
|
|
|
15
|
$self->{'host'}=$param{'host'} || 'localhost'; |
69
|
1
|
|
50
|
|
|
8
|
$self->{'port'}=$param{'port'} || '2947'; |
70
|
1
|
50
|
|
|
|
6
|
unless ($param{'do_not_init'}) { #for testing |
71
|
0
|
|
|
|
|
0
|
my $data=$self->retrieve('LKIFCB'); |
72
|
0
|
|
|
|
|
0
|
foreach (keys %$data) { |
73
|
0
|
|
|
|
|
0
|
$self->{$_}=[@{$data->{$_}}]; #there has got to be a better way to do this... |
|
0
|
|
|
|
|
0
|
|
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head2 get |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
Returns a current point object regardless if there is a fix or not. Applications should test if $point->fix is true. |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
my $point=$obj->get(); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=cut |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub get { |
87
|
0
|
|
|
0
|
1
|
0
|
my $self=shift(); |
88
|
0
|
|
|
|
|
0
|
my $data=$self->retrieve('SMDO'); |
89
|
0
|
|
|
|
|
0
|
return Net::GPSD::Point->new($data); |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=head2 subscribe |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
The subscribe method listens to gpsd server in watcher (W command) mode and calls the handler for each point received. The return for the handler will be sent back as the first argument to the handler on the next call. |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
$obj->subscribe(); |
97
|
|
|
|
|
|
|
$obj->subscribe(handler=>\&gpsd_handler, config=>$config); |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=cut |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub subscribe { |
102
|
0
|
|
|
0
|
1
|
0
|
my $self = shift(); |
103
|
0
|
|
|
|
|
0
|
my %param = @_; |
104
|
0
|
|
|
|
|
0
|
my $last=undef(); |
105
|
0
|
|
0
|
|
|
0
|
my $handler=$param{'handler'} || \&default_point_handler; |
106
|
0
|
|
0
|
|
|
0
|
my $satlisthandler=$param{'satlisthandler'} || \&default_satellitelist_handler; |
107
|
0
|
|
0
|
|
|
0
|
my $config=$param{'config'} || {}; |
108
|
0
|
|
|
|
|
0
|
my $sock = IO::Socket::INET->new(PeerAddr=>$self->host, |
109
|
|
|
|
|
|
|
PeerPort=>$self->port); |
110
|
0
|
|
|
|
|
0
|
$sock->send("W\n"); |
111
|
0
|
|
|
|
|
0
|
my $data; |
112
|
|
|
|
|
|
|
my $point; |
113
|
0
|
|
|
|
|
0
|
while (defined($_=$sock->getline)) { |
114
|
0
|
0
|
|
|
|
0
|
if (m/,O=/) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
115
|
0
|
|
|
|
|
0
|
$point=Net::GPSD::Point->new($self->parse($_)); |
116
|
0
|
0
|
|
|
|
0
|
$point->mode(defined($point->tag) ? (defined($point->alt) ? 3 : 2) : 0); |
|
|
0
|
|
|
|
|
|
117
|
0
|
0
|
|
|
|
0
|
if ($point->fix) { |
118
|
0
|
|
|
|
|
0
|
my $return=&{$handler}($last, $point, $config); |
|
0
|
|
|
|
|
0
|
|
119
|
0
|
0
|
|
|
|
0
|
$last=$return if (defined($return)); |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
} elsif (m/,W=/) { |
122
|
|
|
|
|
|
|
} elsif (m/,Y=/) { |
123
|
|
|
|
|
|
|
} elsif (m/,X=/) { |
124
|
|
|
|
|
|
|
} else { |
125
|
0
|
|
|
|
|
0
|
warn "Unknown: $_\n"; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=head2 default_point_handler |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=cut |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub default_point_handler { |
135
|
0
|
|
|
0
|
1
|
0
|
my $p1=shift(); #last return or undef if first |
136
|
0
|
|
|
|
|
0
|
my $p2=shift(); #current fix |
137
|
0
|
|
|
|
|
0
|
my $config=shift(); #configuration data |
138
|
0
|
|
|
|
|
0
|
print $p2->latlon. "\n"; |
139
|
0
|
|
|
|
|
0
|
return $p2; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head2 default_satellitelist_handler |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=cut |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub default_satellitelist_handler { |
147
|
0
|
|
|
0
|
1
|
0
|
my $sl=shift(); |
148
|
0
|
|
|
|
|
0
|
my $i=0; |
149
|
0
|
|
|
|
|
0
|
print join("\t", qw{Count PRN ELEV Azim SNR USED}), "\n"; |
150
|
0
|
|
|
|
|
0
|
foreach (@$sl) { |
151
|
0
|
|
|
|
|
0
|
print join "\t", ++$i, |
152
|
|
|
|
|
|
|
$_->prn, |
153
|
|
|
|
|
|
|
$_->elev, |
154
|
|
|
|
|
|
|
$_->azim, |
155
|
|
|
|
|
|
|
$_->snr, |
156
|
|
|
|
|
|
|
$_->used; |
157
|
0
|
|
|
|
|
0
|
print "\n"; |
158
|
|
|
|
|
|
|
} |
159
|
0
|
|
|
|
|
0
|
return 1; |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head2 getsatellitelist |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
Returns a list of Net::GPSD::Satellite objects. (maps to gpsd Y command) |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
my @list=$obj->getsatellitelist; |
167
|
|
|
|
|
|
|
my $list=$obj->getsatellitelist; |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=cut |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub getsatellitelist { |
172
|
0
|
|
|
0
|
1
|
0
|
my $self=shift(); |
173
|
0
|
|
|
|
|
0
|
my $string='Y'; |
174
|
0
|
|
|
|
|
0
|
my $data=$self->retrieve($string); |
175
|
0
|
|
|
|
|
0
|
my @data = @{$data->{'Y'}}; |
|
0
|
|
|
|
|
0
|
|
176
|
0
|
|
|
|
|
0
|
shift(@data); #Drop sentence tag |
177
|
0
|
|
|
|
|
0
|
my @list = (); |
178
|
0
|
|
|
|
|
0
|
foreach (@data) { |
179
|
|
|
|
|
|
|
#print "$_\n"; |
180
|
0
|
|
|
|
|
0
|
push @list, Net::GPSD::Satellite->new(split " ", $_); |
181
|
|
|
|
|
|
|
} |
182
|
0
|
0
|
|
|
|
0
|
return wantarray ? @list : \@list; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=head2 retrieve |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=cut |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub retrieve { |
190
|
0
|
|
|
0
|
1
|
0
|
my $self=shift(); |
191
|
0
|
|
|
|
|
0
|
my $string=shift(); |
192
|
0
|
|
|
|
|
0
|
my $sock=$self->open(); |
193
|
0
|
0
|
|
|
|
0
|
if (defined($sock)) { |
194
|
0
|
0
|
|
|
|
0
|
$sock->send($string) or die("Error: $!"); |
195
|
0
|
|
|
|
|
0
|
my $data=$sock->getline; |
196
|
0
|
|
|
|
|
0
|
chomp $data; |
197
|
0
|
|
|
|
|
0
|
return $self->parse($data); |
198
|
|
|
|
|
|
|
} else { |
199
|
0
|
|
|
|
|
0
|
warn "$0: Could not connect to gspd host.\n"; |
200
|
0
|
|
|
|
|
0
|
return undef(); |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=head2 open |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=cut |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
sub open { |
209
|
0
|
|
|
0
|
1
|
0
|
my $self=shift(); |
210
|
0
|
0
|
0
|
|
|
0
|
if (! defined($self->{'sock'}) || ! defined($self->{'sock'}->connected())) { |
211
|
0
|
|
|
|
|
0
|
$self->{'sock'} = IO::Socket::INET->new(PeerAddr => $self->host, |
212
|
|
|
|
|
|
|
PeerPort => $self->port); |
213
|
|
|
|
|
|
|
} |
214
|
0
|
|
|
|
|
0
|
return $self->{'sock'}; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=head2 parse |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=cut |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub parse { |
222
|
0
|
|
|
0
|
1
|
0
|
my $self=shift(); |
223
|
0
|
|
|
|
|
0
|
my $line=shift(); |
224
|
0
|
|
|
|
|
0
|
my %data=(); |
225
|
0
|
|
|
|
|
0
|
my @line=split(/[,\n\r]/, $line); |
226
|
0
|
|
|
|
|
0
|
foreach (@line) { |
227
|
0
|
0
|
|
|
|
0
|
if (m/(.*)=(.*)/) { |
228
|
0
|
0
|
|
|
|
0
|
if ($1 eq 'Y') { |
229
|
0
|
|
|
|
|
0
|
$data{$1}=[split(/:/, $2)]; #Y is : delimited |
230
|
|
|
|
|
|
|
} else { |
231
|
0
|
0
|
|
|
|
0
|
$data{$1}=[map {$_ eq '?' ? undef() : $_} split(/\s+/, $2)]; |
|
0
|
|
|
|
|
0
|
|
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
} |
235
|
0
|
|
|
|
|
0
|
return \%data; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=head2 host |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Sets or returns the current gpsd host. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
my $host=$obj->host; |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=cut |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub host { |
247
|
3
|
|
|
3
|
1
|
43
|
my $self = shift(); |
248
|
3
|
100
|
|
|
|
10
|
if (@_) { |
249
|
1
|
|
|
|
|
2
|
$self->{'host'} = shift(); |
250
|
|
|
|
|
|
|
} |
251
|
3
|
|
|
|
|
32
|
return $self->{'host'}; |
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=head2 port |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
Sets or returns the current gpsd TCP port. |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
my $port=$obj->port; |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
=cut |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
sub port { |
263
|
5
|
|
|
5
|
1
|
9
|
my $self = shift(); |
264
|
5
|
100
|
|
|
|
10
|
if (@_) { |
265
|
2
|
|
|
|
|
5
|
$self->{'port'} = shift(); |
266
|
|
|
|
|
|
|
} |
267
|
5
|
|
|
|
|
13
|
return $self->{'port'}; |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=head2 baud |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Returns the baud rate of the connect GPS receiver. (maps to gpsd B command first data element) |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
my $baud=$obj->baud; |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=cut |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub baud { |
279
|
0
|
|
|
0
|
1
|
0
|
my $self = shift(); |
280
|
0
|
|
|
|
|
0
|
return q2u $self->{'B'}->[0]; |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=head2 rate |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
Returns the sampling rate of the GPS receiver. (maps to gpsd C command first data element) |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
my $rate=$obj->rate; |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
=cut |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
sub rate { |
292
|
0
|
|
|
0
|
1
|
0
|
my $self = shift(); |
293
|
0
|
|
|
|
|
0
|
return q2u $self->{'C'}->[0]; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=head2 device |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Returns the GPS device name. (maps to gpsd F command first data element) |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
my $device=$obj->device; |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=cut |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
sub device { |
305
|
0
|
|
|
0
|
1
|
0
|
my $self = shift(); |
306
|
0
|
|
|
|
|
0
|
return q2u $self->{'F'}->[0]; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
=head2 identification (aka id) |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
Returns a text string identifying the GPS. (maps to gpsd I command first data element) |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
my $identification=$obj->identification; |
314
|
|
|
|
|
|
|
my $identification=$obj->id; |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
=cut |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
sub identification { |
319
|
0
|
|
|
0
|
1
|
0
|
my $self = shift(); |
320
|
0
|
|
|
|
|
0
|
return q2u $self->{'I'}->[0]; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=head2 id |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=cut |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
sub id { |
328
|
0
|
|
|
0
|
1
|
0
|
my $self = shift(); |
329
|
0
|
|
|
|
|
0
|
return $self->identification; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=head2 protocol |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
Returns the GPSD protocol revision number. (maps to gpsd L command first data element) |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
my $protocol=$obj->protocol; |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
=cut |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
sub protocol { |
341
|
0
|
|
|
0
|
1
|
0
|
my $self = shift(); |
342
|
0
|
|
|
|
|
0
|
return q2u $self->{'L'}->[0]; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=head2 daemon |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
Returns the gpsd daemon version. (maps to gpsd L command second data element) |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
my $daemon=$obj->daemon; |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=cut |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
sub daemon { |
354
|
0
|
|
|
0
|
1
|
0
|
my $self = shift(); |
355
|
0
|
|
|
|
|
0
|
return q2u $self->{'L'}->[1]; |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
=head2 commands |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
Returns a string of accepted command letters. (maps to gpsd L command third data element) |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
my $commands=$obj->commands; |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
=cut |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
sub commands { |
367
|
0
|
|
|
0
|
1
|
0
|
my $self = shift(); |
368
|
0
|
|
|
|
|
0
|
my $string=q2u $self->{'L'}->[2]; |
369
|
0
|
0
|
|
|
|
0
|
return wantarray ? split(//, $string) : $string |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
=head1 FUNCTIONS |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
=head2 time |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
Returns the time difference between two point objects in seconds. |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
my $seconds=$obj->time($p1, $p2); |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
=cut |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
sub time { |
383
|
|
|
|
|
|
|
#seconds between p1 and p2 |
384
|
2
|
|
|
2
|
1
|
3
|
my $self=shift(); |
385
|
2
|
|
|
|
|
3
|
my $p1=shift(); |
386
|
2
|
|
|
|
|
3
|
my $p2=shift(); |
387
|
2
|
|
|
|
|
5
|
return abs($p2->time - $p1->time); |
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=head2 distance |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
Returns the distance difference between two point objects in meters. (simple calculation) |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
my $meters=$obj->distance($p1, $p2); |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
=cut |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub distance { |
399
|
|
|
|
|
|
|
#returns meters between p1 and p2 |
400
|
2
|
|
|
2
|
1
|
8
|
my $self=shift(); |
401
|
2
|
|
|
|
|
3
|
my $p1=shift(); |
402
|
2
|
|
|
|
|
2
|
my $p2=shift(); |
403
|
2
|
|
|
|
|
6
|
my $lat1=$p1->lat; |
404
|
2
|
|
|
|
|
7
|
my $lon1=$p1->lon; |
405
|
2
|
|
|
|
|
5
|
my $lon2=$p2->lon; |
406
|
2
|
|
|
|
|
6
|
my $lat2=$p2->lat; |
407
|
|
|
|
|
|
|
|
408
|
1
|
|
|
1
|
|
677
|
use Geo::Inverse; |
|
1
|
|
|
|
|
3676
|
|
|
1
|
|
|
|
|
92
|
|
409
|
2
|
|
|
|
|
11
|
my $obj = Geo::Inverse->new(); |
410
|
2
|
|
|
|
|
530
|
my ($faz, $baz, $dist)=$obj->inverse($lat1, $lon1, $lat2, $lon2); |
411
|
2
|
|
|
|
|
387
|
return $dist; |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
=head2 track |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
Returns a point object at the predicted location in time seconds assuming constant velocity. (Geo::Forward calculation) |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
my $point=$obj->track($p1, $seconds); |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=cut |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
sub track { |
423
|
|
|
|
|
|
|
#return calculated point of $p1 in time assuming constant velocity |
424
|
1
|
|
|
1
|
1
|
39
|
my $self=shift(); |
425
|
1
|
|
|
|
|
2
|
my $p1=shift(); |
426
|
1
|
|
|
|
|
2
|
my $time=shift(); |
427
|
1
|
|
|
1
|
|
732
|
use Geo::Forward; |
|
1
|
|
|
|
|
1761
|
|
|
1
|
|
|
|
|
168
|
|
428
|
1
|
|
|
|
|
13
|
my $object = Geo::Forward->new(); # default "WGS84" |
429
|
1
|
|
50
|
|
|
269
|
my $dist=($p1->speed||0) * $time; #meters |
430
|
1
|
|
50
|
|
|
5
|
my ($lat1,$lon1,$faz)=($p1->lat, $p1->lon, $p1->heading||0); |
431
|
1
|
|
|
|
|
6
|
my ($lat2,$lon2,$baz) = $object->forward($lat1,$lon1,$faz,$dist); |
432
|
|
|
|
|
|
|
|
433
|
1
|
|
|
|
|
153
|
my $p2=Net::GPSD::Point->new($p1); |
434
|
1
|
|
|
|
|
4
|
$p2->lat($lat2); |
435
|
1
|
|
|
|
|
4
|
$p2->lon($lon2); |
436
|
1
|
|
|
|
|
4
|
$p2->time($p1->time + $time); |
437
|
1
|
|
|
|
|
6
|
$p2->heading($baz-180); |
438
|
1
|
|
|
|
|
13
|
return $p2; |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
=head2 q2u |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
=cut |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
sub q2u { |
446
|
0
|
|
|
0
|
1
|
|
my $a=shift(); |
447
|
0
|
0
|
|
|
|
|
return $a eq '?' ? undef() : $a; |
448
|
|
|
|
|
|
|
} |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
=head1 GETTING STARTED |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
Try the examples in the bin folder. Most every method has a default which is most likely what you will want. |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=head1 LIMITATIONS |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
The distance function is Geo::Inverse. |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
The track function uses Geo::Forward. |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
All units are degrees, meters, seconds. |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
=head1 BUGS |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
Email the author and log on RT. |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
=head1 EXAMPLES |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
=begin html |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
example-get.pl |
472
|
|
|
|
|
|
|
example-subscribe.pl |
473
|
|
|
|
|
|
|
example-subscribe-handler.pl |
474
|
|
|
|
|
|
|
example-check.pl |
475
|
|
|
|
|
|
|
example-information.pl |
476
|
|
|
|
|
|
|
example-getsatellitelist.pl |
477
|
|
|
|
|
|
|
example-tracker.pl |
478
|
|
|
|
|
|
|
example-tracker-http.pl |
479
|
|
|
|
|
|
|
example-tracker-text.pl |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
=end html |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
=head1 SUPPORT |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
DavisNetworks.com supports all Perl applications including this package. |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=head1 AUTHOR |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
Michael R. Davis, qw/gpsd michaelrdavis com/ |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
=head1 LICENSE |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
Copyright (c) 2006 Michael R. Davis (mrdvt92) |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=head1 SEE ALSO |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
L, L |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
=cut |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
1; |