ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-GPSD/GPSD.pm
(Generate patch)

Comparing AnyEvent-GPSD/GPSD.pm (file contents):
Revision 1.4 by root, Fri Jul 18 01:31:12 2008 UTC vs.
Revision 1.5 by root, Fri Jul 25 13:22:18 2008 UTC

140 $self->connect; 140 $self->connect;
141 141
142 $self 142 $self
143} 143}
144 144
145sub DESTROY {
146 my ($self) = @_;
147
148 $self->record_log;
149}
150
145sub event { 151sub event {
146 my $event = splice @_, 1, 1, (); 152 my $event = splice @_, 1, 1, ();
147 153
148 warn "event<$event,@_>\n";#d# 154 #warn "event<$event,@_>\n";#d#
149 if ($event = $_[0]{"on_$event"}) { 155 if ($event = $_[0]{"on_$event"}) {
150 &$event; 156 &$event;
151 } 157 }
152} 158}
153 159
214 }, 220 },
215 on_read => sub { 221 on_read => sub {
216 $_[0]{rbuf} =~ s/^([^\015\012]*)\015\012// 222 $_[0]{rbuf} =~ s/^([^\015\012]*)\015\012//
217 or return; 223 or return;
218 224
219 $self->feed ($1); 225 $self->feed ($1)
226 unless $self->{replay_cb};
220 }, 227 },
221 ; 228 ;
222 229
223 $self->send ("w"); 230 $self->send ("w");
224 $self->send ("o"); 231 $self->send ("o");
281 if (@data > 3) { 288 if (@data > 3) {
282 # the gpsd time is virtually useless as it is truncated :/ 289 # the gpsd time is virtually useless as it is truncated :/
283 for (qw(tag _time _terr lat lon alt herr verr bearing speed vspeed berr serr vserr mode)) { 290 for (qw(tag _time _terr lat lon alt herr verr bearing speed vspeed berr serr vserr mode)) {
284 $type = shift @data; 291 $type = shift @data;
285 $fix->{$_} = $type eq "?" ? undef : $type; 292 $fix->{$_} = $type eq "?" ? undef : $type;
293 }
294
295 if (my $s = $self->{stretch}) {
296 $s = 1 / $s;
297
298 $fix->{herr} *= $s; # ?
299 $fix->{verr} *= $s; # ?
300 $fix->{berr} *= $s; # ?
301 $fix->{serr} *= $s; # ?
302 $fix->{vserr} *= $s; # ?
303
304 $fix->{speed} *= $s;
305 $fix->{vspeed} *= $s;
286 } 306 }
287 307
288 $fix->{mode} = 2 if $fix->{mode} eq "?"; # arbitrary choice 308 $fix->{mode} = 2 if $fix->{mode} eq "?"; # arbitrary choice
289 } else { 309 } else {
290 $fix->{mode} = 1; 310 $fix->{mode} = 1;
363 383
364 syswrite $self->{logfh}, JSON::encode_json ([AnyEvent->time, @arg]) . "\n" 384 syswrite $self->{logfh}, JSON::encode_json ([AnyEvent->time, @arg]) . "\n"
365 if $self->{logfh}; 385 if $self->{logfh};
366} 386}
367 387
388=item $gps->record_log ($path)
389
390If C<$path> is defined, then that file will be created or truncated and a
391log of all (raw) packets received will be written to it. This log file can
392later be replayed by calling C<< $gps->replay_log ($path) >>.
393
394If C<$path> is undefined then the log will be closed.
395
396=cut
397
368sub record_log { 398sub record_log {
369 my ($self, $path) = @_, 399 my ($self, $path) = @_;
370 400
401 if (defined $path) {
402 $self->record_log;
403
371 require JSON; 404 require JSON;
372 405
373 open $self->{logfh}, ">", $path 406 open $self->{logfh}, ">:perlio", $path
374 or Carp::croak "$path: $!"; 407 or Carp::croak "$path: $!";
375 408
376 $self->log (start => $VERSION); 409 $self->log (start => $VERSION, 0, 0, { interval => $self->{interval} });
410 } elsif ($self->{logfh}) {
411 $self->log ("stop");
412 delete $self->{logfh};
413 }
414}
415
416=item $gps->replay_log ($path, %options)
417
418Replays a log file written using C<record_log> (or stops replaying when
419C<$path> is undefined). While the log file replays, real GPS events will
420be ignored. This comes in handy when testing.
421
422Please note that replaying a log will change configuration options that
423will not be restored, so it's best not to reuse a gpsd object after a
424replay.
425
426The options include:
427
428=over 4
429
430=item compress => 1
431
432If set to a true value (default: false), then passages without fix will be
433replayed much faster than passages with fix. The same happens for passages
434without much movement.
435
436=item stretch => $factor
437
438Multiplies all times by the given factor. Values < 1 make the log replay
439faster, values > 1 slower. Note that the frequency of fixes will not be
440increased, o stretch factors > 1 do not work well. =back
441
442=cut
443
444sub replay_log {
445 my ($self, $path, %option) = @_;
446
447 if (defined $path) {
448 $self->replay_log;
449
450 require JSON;
451
452 open my $fh, "<:perlio", $path
453 or Carp::croak "$path: $!";
454
455 $self->{stretch} = $option{stretch} || 1;
456 $self->{compress} = $option{compress};
457
458 $self->{imterval} /= $self->{stretch};
459
460 Scalar::Util::weaken $self;
461
462 $self->{replay_cb} = sub {
463 my $line = <$fh>;
464
465 if (2 > length $line) {
466 $self->replay_log;
467 } else {
468 my ($time, $type, @data) = @{ JSON::decode_json ($line) };
469
470 $time *= $self->{stretch};
471
472 if ($type eq "start") {
473 my ($module_version, $major_version, $minor_version, $args) = @data;
474
475 $self->{interval} = ($args->{interval} || 1) / $self->{stretch};
476 }
477
478 if (
479 $type eq "start"
480 or ($self->{compress}
481 and $self->{fix} && ($self->{fix}{mode} < 2 || $self->{fix}{speed} < 5))
482 ) {
483 $self->{replay_now} = $time;
484 }
485
486 $self->{replay_timer} = AnyEvent->timer (after => $time - $self->{replay_now}, cb => sub {
487 $self->{replay_now} = $time;
488 $self->{command} = []; # no can do
489 $self->feed ($data[0]) if $type eq "raw";
490 $self->{replay_cb}();
491 });
492 }
493 };
494
495 $self->{replay_cb}();
496
497 } else {
498 delete $self->{stretch};
499 delete $self->{compress};
500 delete $self->{replay_timer};
501 delete $self->{replay_cb};
502 }
377} 503}
378 504
379=back 505=back
380 506
381=head1 SEE ALSO 507=head1 SEE ALSO

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines