This file is indexed.

/usr/share/perl5/Net/GPSD3.pm is in libnet-gpsd3-perl 0.19-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
package Net::GPSD3;
use strict;
use warnings;
use base qw{Net::GPSD3::Base};
use JSON::XS qw{};
use IO::Socket::INET6 qw{};
use Net::GPSD3::Return::Unknown;
use Net::GPSD3::Cache;
use DateTime;

our $VERSION='0.19';
our $PACKAGE=__PACKAGE__;

=head1 NAME

Net::GPSD3 - Interface to the gpsd server daemon protocol versions 3 (JSON).

=head1 SYNOPSIS

=head2 Watch Interface

  use Net::GPSD3;
  my $gpsd=Net::GPSD3->new;
  $gpsd->watch;

One Liner

  perl -MNet::GPSD3 -e 'Net::GPSD3->new->watch'

=head2 Poll Interface

  use Net::GPSD3;
  use Data::Dumper qw{Dumper};
  my $gpsd=Net::GPSD3->new;
  my $poll=$gpsd->poll;
  print Dumper($poll);

One Liner

  perl -MNet::GPSD3 -e 'printf "Protocol: %s\n", Net::GPSD3->new->poll->parent->cache->VERSION->protocol;'

  Protocol: 3.4

=head2 POE Interface

See L<Net::GPSD3::POE>

=head1 DESCRIPTION

Net::GPSD3 provides an object client interface to the gpsd server daemon utilizing the version 3 protocol. gpsd is an open source GPS daemon from http://www.catb.org/gpsd/  Support for Version 3 of the protocol (JSON) was added to the daemon in version 2.90.  If your daemon is before 2.90 (protocol 2.X), please use the L<Net::GPSD> package.

=head1 CONSTRUCTOR

=head2 new

Returns a new Net::GPSD3 object.

  my $gpsd=Net::GPSD3->new;
  my $gpsd=Net::GPSD3->new(host=>"127.0.0.1", port=>2947); #defaults

=head1 METHODS

=head2 host

Sets or returns the current gpsd host.

 my $host=$obj->host;

=cut

sub host {
  my $self=shift;
  if (@_) {
    $self->{'host'}=shift;
    undef($self->{'socket'});
  }
  $self->{'host'}="127.0.0.1" unless defined $self->{'host'};
  return $self->{'host'};
}

=head2 port

Sets or returns the current gpsd TCP port.

 my $port=$obj->port;

=cut

sub port {
  my $self=shift;
  if (@_) {
    $self->{'port'}=shift;
    undef($self->{'socket'});
  }
  $self->{'port'}='2947' unless defined $self->{'port'};
  return $self->{'port'};
}

=head2 poll

Sends a Poll request to the gpsd server and returns a L<Net::GPSD3::Return::POLL> object. The method also populates the cache object with the L<Net::GPSD3::Return::VERISON> and L<Net::GPSD3::Return::DEVICES> objects.

  my $poll=$gpsd->poll; #isa Net::GPSD3::Return::POLL object

Note: In order to use the poll method consistently you should run the GPSD daemon as a service.  You may also need to run the daemon with the "-n" option.

=cut

sub poll {
  my $self=shift;
  $self->socket->send(qq(?DEVICES;\n)) unless $self->cache->DEVICES;
  $self->socket->send(qq(?POLL;\n));
  my $object;
  do { #Reads and caches VERSION and DEVICES
    local $/="\r\n";
    my $line=$self->socket->getline;
    chomp $line;
    $object=$self->constructor($self->decode($line), string=>$line);
    $self->cache->add($object) unless $object->class eq "POLL";
  } until $object->class eq "POLL"; #this needs more logic
  return $object;
}

=head2 watch

Calls all handlers that are registered in the handler method.

  $gpsd->watch;  #will not return unless something goes wrong.

=cut

sub watch {
  my $self=shift;
  my @handler=$self->handlers;
  push @handler, \&default_handler unless scalar(@handler);
  #$self->socket->send(qq(?DEVICES;\n)); #appears this is now done in the daemon
  $self->socket->send($self->_watch_string_on. "\n");
  my $object;
  #man 8 gpsd - Each request returns a line of response text ended by a CR/LF.
  local $/="\r\n";
  my $line;
  while (defined($line=$self->socket->getline)) { #Reads VERSION and DEVICES object too.
    #print "$line\n";
    chomp $line;
    my $object=$self->constructor($self->decode($line), string=>$line);
    $_->($object) foreach @handler;
    $self->cache($object); #cache after handler so that the last point is available to the handler.
  }
  return $self;
}

sub _watch_string_on {
  return q(?WATCH={"enable":true,"json":true};);
}

sub _watch_string_off {
  return q(?WATCH={"enable":false,"json":true};);
}

=head2 addHandler

Adds handlers to the handler list.

  $gpsd->addHandler(\&myHandler);
  $gpsd->addHandler(\&myHandler1, \&myHandler2);

A handler is a sub reference where the first argument is a Net::GPSD3::Return::* object.

=cut

sub addHandler {
  my $self=shift;
  my $array=$self->handlers;
  push @$array, @_ if @_;
  return $self;
}

=head2 handlers

List of handlers that are called in order to process objects from the gpsd wathcer stream.  

  my @handler=$gpsd->handlers; #()
  my $handler=$gpsd->handlers; #[]

=cut

sub handlers {
  my $self=shift;
  $self->{'handler'}=[] unless ref($self->{'handler'});
  return wantarray ? @{$self->{'handler'}} : $self->{'handler'};
}

=head2 cache

Returns the L<Net::GPSD3::Cache> caching object.

=cut

sub cache {
  my $self=shift;
  $self->{"cache"}=Net::GPSD3::Cache->new(parent=>$self)
    unless defined $self->{"cache"};
  return $self->{"cache"};
}

=head1 METHODS Internal

=head2 default_handler

=cut

sub default_handler {
  my $object=shift;
  #use Data::Dumper qw{Dumper};
  #print Dumper($object);
  if ($object->class eq "TPV") {
    printf "%s: %s, Time: %s, Lat: %s, Lon: %s, Speed: %s, Heading: %s\n",
             DateTime->now,
             $object->class,
             $object->timestamp,
             $object->lat,
             $object->lon,
             $object->speed,
             $object->track;
  } elsif ($object->class eq "SKY") {
    printf "%s: %s, Satellites: %s, Used: %s, PRNs: %s\n",
             DateTime->now,
             $object->class,
             $object->reported,
             $object->used,
             join(",", map {$_->prn} grep {$_->used} $object->Satellites),
  } elsif ($object->class eq "SUBFRAME") {
    printf qq{%s: %s, Device: %s\n},
             DateTime->now,
             $object->class,
             $object->device;
  } elsif ($object->class eq "VERSION") {
    printf "%s: %s, GPSD: %s (%s), %s: %s\n",
             DateTime->now,
             $object->class,
             $object->release,
             $object->revision,
             ref($object->parent),
             $object->parent->VERSION;
  } elsif ($object->class eq "WATCH") {
    printf "%s: %s, Enabled: %s\n",
             DateTime->now,
             $object->class,
             $object->enabled;
  } elsif ($object->class eq "DEVICES") {
    my @device=$object->Devices;
    foreach my $device (@device) {
      if ($device->activated) {
        $device=sprintf("%s (%s bps %s-%s)", $device->path, $device->bps, $device->driver, $device->subtype);
      } else {
        $device=$device->path;
      }
    }
    printf "%s: %s, Devices: %s\n",
             DateTime->now,
             $object->class,
             join(", ", @device);
  } elsif ($object->class eq "DEVICE") {
    printf qq{%s: %s, Device: %s (%s bps %s-%s)\n},
             DateTime->now,
             $object->class,
             $object->path,
             $object->bps,
             $object->driver,
             $object->subtype;
  } elsif ($object->class eq "ERROR") {
    printf qq{%s: %s, Message: "%s"\n},
             DateTime->now,
             $object->class,
             $object->message;
  } else {
    warn(sprintf(qq{Warning: Unknown class "%s" for object "%s".}, $object->class, ref($object)));
    #print Dumper($object);
  }
  #print Dumper($object);
}

=head2 socket

Returns the cached L<IO::Socket::INET6> object

  my $socket=$gpsd->socket;  #try to reconnect on failure

=cut

sub socket {
  my $self=shift;
  unless (defined($self->{'socket'}) and
            defined($self->{'socket'}->connected)) { 
    $self->{"socket"}=IO::Socket::INET6->new(
                        PeerAddr => $self->host,
                        PeerPort => $self->port,
                      );
    die(sprintf("Error: Cannot connect to gpsd://%s:%s/.\n",
      $self->host, $self->port)) unless defined($self->{"socket"});
  }
  return $self->{'socket'};
}

=head2 json

Returns the cached L<JSON::XS> object

=cut

sub json {
  my $self=shift;
  #Do I need to support JSON::PP?
  $self->{"json"}=JSON::XS->new unless ref($self->{"json"}) eq "JSON::XS";
  return $self->{"json"};
}

=head2 decode

Returns a perl data structure given a JSON formated string.

  my %data=$gpsd->decode($string); #()
  my $data=$gpsd->decode($string); #{}

=cut

sub decode {
  my $self=shift;
  my $string=shift;
  my $data=eval {$self->json->decode($string)};
  if ($@) {
    $data={class=>"ERROR", message=>"Invalid JSON"};
  }
  return wantarray ? %$data : $data;
}

=head2 encode

Returns a JSON string from a perl data structure

=cut

sub encode {
  my $self=shift;
  my $data=shift;
  my $string=$self->json->encode($data);
  return $string;
}

=head2 constructor

Constructs a class object by lazy loading the classes.

  my $obj=$gpsd->constructor(%$data);
  my $obj=$gpsd->constructor(class=>"DEVICE",
                             string=>'{...}',
                             ...);

Returns and object in the Net::GPSD3::Return::* namespace.

=cut

sub constructor {
  my $self=shift;
  my %data=@_;
  $data{"class"}||="undef";
  my $class=join("::", $PACKAGE, "Return", $data{"class"});
  my $object;
  eval("use $class");
  if ($@) { #Failed to load class
    $object=Net::GPSD3::Return::Unknown->new(parent=>$self, %data);
  } else {
    $object=$class->new(parent=>$self, %data);
  }
  return $object;
}

=head1 BUGS

Log on RT and Send to gpsd-dev email list

There are no two GPS devices that are alike.  Each GPS device has a different GPSD signature as well. If your GPS device does not work out of the box with this package, please send me a log of your devices JSON sentences.

  echo '?POLL;' | nc 127.0.0.1 2947

  echo '?WATCH={"enable":true,"json":true};' | socat -t10 stdin stdout | nc 127.0.0.1 2947

=head1 SUPPORT

DavisNetworks.com supports all Perl applications including this package.

Try gpsd-dev email list

=head1 AUTHOR

  Michael R. Davis
  CPAN ID: MRDVT
  STOP, LLC
  domain=>michaelrdavis,tld=>com,account=>perl
  http://www.stopllc.com/

=head1 COPYRIGHT

This program is free software licensed under the...

  The BSD License

The full text of the license can be found in the LICENSE file included with this module.

=head1 SEE ALSO

L<Net::GPSD>, L<Net::GPSD3::POE>, L<GPS::Point>, L<JSON::XS>, L<IO::Socket::INET6>, L<DateTime>

=cut

1;