--- AnyEvent-GPSD/GPSD.pm 2008/07/02 04:57:02 1.1 +++ AnyEvent-GPSD/GPSD.pm 2008/07/02 05:17:37 1.2 @@ -95,8 +95,14 @@ =item on_fix => $cb->({point}) -Called regularly. The C<{point}> hash contains at least the following -members: +Called regularly (usually about once/second), even when there is no +connection to the GPSD (so is useful to update your idea of the current +position). The passed hash reference must I be modified in any way. + +If C is C<2> or C<3>, then the C<{point}> hash contains at least the +following members, otherwise it is undefined which members exist. Members +whose values are not known are C (usually the error values, speed +and so on). time when this fix was received (s) @@ -124,8 +130,11 @@ my $class = shift; my $self = bless { @_, + interval => 1, + fix => { time => AnyEvent->now, mode => 1 }, }, $class; + $self->interval_timer; $self->connect; $self @@ -152,6 +161,22 @@ }); } +# make sure we send "no fix" updates when we lose connectivity +sub interval_timer { + my ($self) = @_; + + $self->{interval_w} = AnyEvent->timer (after => $self->{interval}, cb => sub { + if (AnyEvent->now - $self->{fix}{time} > $self->{interval} * 1.9) { + $self->{fix}{mode} = 1; + $self->event (fix => $self->{fix}); + } + + $self->interval_timer; + }); + + Scalar::Util::weaken $self; +} + sub connect { my ($self) = @_; @@ -179,7 +204,7 @@ $self->retry; }, on_eof => sub { - $! = &Errno::EBADMSG; + $! = &Errno::EPIPE; $self->event ("error"); $self->retry; }, @@ -194,6 +219,7 @@ $self->send ("w"); $self->send ("o"); $self->send ("y"); + $self->send ("c"); $self->event ("connect"); } else { @@ -237,19 +263,24 @@ if ($type eq "O") { my @data = split /\s+/, $data; - my %fix = (time => $self->{now}); + + my $fix = $self->{fix}; + + $fix->{time} = $self->{now}; if (@data > 3) { # the gpsd time is virtually useless as it is truncated :/ - $fix{$_} = shift @data for qw(tag _time _terr lat lon alt herr verr bearing speed vspeed berr serr vserr mode); + for (qw(tag _time _terr lat lon alt herr verr bearing speed vspeed berr serr vserr mode)) { + $type = shift @data; + $fix->{$_} = $type eq "?" ? undef : $type; + } - $fix{mode} = 2 if $fix{mode} eq "?"; # arbitrary choice + $fix->{mode} = 2 if $fix->{mode} eq "?"; # arbitrary choice } else { - $fix{mode} = 1; + $fix->{mode} = 1; } - $self->{fix} = \%fix; - $self->event (fix => \%fix); + $self->event (fix => $fix); } elsif ($type eq "Y") { my (undef, @sats) = split /:/, $data; @@ -266,6 +297,9 @@ } @sats]; $self->event (satellite_update => $self->{satellite_info}); + + } elsif ($type eq "C") { + $self->{interval} = $data >= 1 ? $data * 1 : 1; } # we (wrongly) assume that gpsd responses are always in response