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.1 by root, Wed Jul 2 04:57:02 2008 UTC vs.
Revision 1.3 by root, Wed Jul 2 05:21:58 2008 UTC

88 88
89C<snr> contains the signal strength in decibals (28+ is usually the 89C<snr> contains the signal strength in decibals (28+ is usually the
90minimum value for a good fix). 90minimum value for a good fix).
91 91
92C<fix> contains either C<1> to indicate that this satellite was used for 92C<fix> contains either C<1> to indicate that this satellite was used for
93the last position fix, C<0> otherwise. EGNOS/WAAS etc. satellites will 93the last position fix, C<0> otherwise. EGNOS/WAAS etc. satellites will
94always show as C<0>, even if their correction info was used. 94always show as C<0>, even if their correction info was used.
95 95
96The passed hash references are read-only.
97
96=item on_fix => $cb->({point}) 98=item on_fix => $cb->({point})
97 99
98Called regularly. The C<{point}> hash contains at least the following 100Called regularly (usually about once/second), even when there is no
99members: 101connection to the GPSD (so is useful to update your idea of the current
102position). The passed hash reference must I<not> be modified in any way.
103
104If C<mode> is C<2> or C<3>, then the C<{point}> hash contains at least the
105following members, otherwise it is undefined which members exist. Members
106whose values are not known are C<undef> (usually the error values, speed
107and so on).
100 108
101 time when this fix was received (s) 109 time when this fix was received (s)
102 110
103 lat latitude (S -90..90 N) 111 lat latitude (S -90..90 N)
104 lon longitude (W -180..180 E) 112 lon longitude (W -180..180 E)
122 130
123sub new { 131sub new {
124 my $class = shift; 132 my $class = shift;
125 my $self = bless { 133 my $self = bless {
126 @_, 134 @_,
135 interval => 1,
136 fix => { time => AnyEvent->now, mode => 1 },
127 }, $class; 137 }, $class;
128 138
139 $self->interval_timer;
129 $self->connect; 140 $self->connect;
130 141
131 $self 142 $self
132} 143}
133 144
148 Scalar::Util::weaken $self; 159 Scalar::Util::weaken $self;
149 $self->{retry_w} = AnyEvent->timer (after => 1, cb => sub { 160 $self->{retry_w} = AnyEvent->timer (after => 1, cb => sub {
150 delete $self->{retry_w}; 161 delete $self->{retry_w};
151 $self->connect; 162 $self->connect;
152 }); 163 });
164}
165
166# make sure we send "no fix" updates when we lose connectivity
167sub interval_timer {
168 my ($self) = @_;
169
170 $self->{interval_w} = AnyEvent->timer (after => $self->{interval}, cb => sub {
171 if (AnyEvent->now - $self->{fix}{time} > $self->{interval} * 1.9) {
172 $self->{fix}{mode} = 1;
173 $self->event (fix => $self->{fix});
174 }
175
176 $self->interval_timer;
177 });
178
179 Scalar::Util::weaken $self;
153} 180}
154 181
155sub connect { 182sub connect {
156 my ($self) = @_; 183 my ($self) = @_;
157 184
177 on_error => sub { 204 on_error => sub {
178 $self->event ("error"); 205 $self->event ("error");
179 $self->retry; 206 $self->retry;
180 }, 207 },
181 on_eof => sub { 208 on_eof => sub {
182 $! = &Errno::EBADMSG; 209 $! = &Errno::EPIPE;
183 $self->event ("error"); 210 $self->event ("error");
184 $self->retry; 211 $self->retry;
185 }, 212 },
186 on_read => sub { 213 on_read => sub {
187 $_[0]{rbuf} =~ s/^([^\015\012]*)\015\012// 214 $_[0]{rbuf} =~ s/^([^\015\012]*)\015\012//
192 ; 219 ;
193 220
194 $self->send ("w"); 221 $self->send ("w");
195 $self->send ("o"); 222 $self->send ("o");
196 $self->send ("y"); 223 $self->send ("y");
224 $self->send ("c");
197 225
198 $self->event ("connect"); 226 $self->event ("connect");
199 } else { 227 } else {
200 $self->event ("error"); 228 $self->event ("error");
201 } 229 }
235 263
236 $self->{state}{$type} = [$data => $self->{now}]; 264 $self->{state}{$type} = [$data => $self->{now}];
237 265
238 if ($type eq "O") { 266 if ($type eq "O") {
239 my @data = split /\s+/, $data; 267 my @data = split /\s+/, $data;
268
269 my $fix = $self->{fix};
270
240 my %fix = (time => $self->{now}); 271 $fix->{time} = $self->{now};
241 272
242 if (@data > 3) { 273 if (@data > 3) {
243 # the gpsd time is virtually useless as it is truncated :/ 274 # the gpsd time is virtually useless as it is truncated :/
244 $fix{$_} = shift @data for qw(tag _time _terr lat lon alt herr verr bearing speed vspeed berr serr vserr mode); 275 for (qw(tag _time _terr lat lon alt herr verr bearing speed vspeed berr serr vserr mode)) {
276 $type = shift @data;
277 $fix->{$_} = $type eq "?" ? undef : $type;
278 }
245 279
246 $fix{mode} = 2 if $fix{mode} eq "?"; # arbitrary choice 280 $fix->{mode} = 2 if $fix->{mode} eq "?"; # arbitrary choice
247 } else { 281 } else {
248 $fix{mode} = 1; 282 $fix->{mode} = 1;
249 } 283 }
250 284
251 $self->{fix} = \%fix;
252 $self->event (fix => \%fix); 285 $self->event (fix => $fix);
253 286
254 } elsif ($type eq "Y") { 287 } elsif ($type eq "Y") {
255 my (undef, @sats) = split /:/, $data; 288 my (undef, @sats) = split /:/, $data;
256 289
257 $self->{satellite_info} = [map { 290 $self->{satellite_info} = [map {
264 fix => $sat[4], 297 fix => $sat[4],
265 } 298 }
266 } @sats]; 299 } @sats];
267 300
268 $self->event (satellite_update => $self->{satellite_info}); 301 $self->event (satellite_update => $self->{satellite_info});
302
303 } elsif ($type eq "C") {
304 $self->{interval} = $data >= 1 ? $data * 1 : 1;
269 } 305 }
270 306
271 # we (wrongly) assume that gpsd responses are always in response 307 # we (wrongly) assume that gpsd responses are always in response
272 # to an earlier command 308 # to an earlier command
273 309
282This returns an estimate of the current position based on the last fix and 318This returns an estimate of the current position based on the last fix and
283the time passed since then. Useful for interactive applications where you 319the time passed since then. Useful for interactive applications where you
284want more frequent updates, but not very useful to store, as the next fix 320want more frequent updates, but not very useful to store, as the next fix
285might well be totally off. 321might well be totally off.
286 322
287If the fix is older then C<$max_seconds> (default: C<1.9>) or if no fix is 323If the fix is older then C<$max_seconds> (default: C<1.9> times the update
288available, returns the empty list. 324interval, i.e. usually C<1.9> seconds) or if no fix is available, returns
325the empty list.
289 326
290=cut 327=cut
291 328
292sub estimate { 329sub estimate {
293 my ($self, $max) = @_; 330 my ($self, $max) = @_;
294 331
295 $max ||= 1.9 unless defined $max; 332 $max ||= 1.9 * $self->{interval} unless defined $max;
296 333
297 my $geo = $self->{geo_forward} ||= new Geo::Forward; 334 my $geo = $self->{geo_forward} ||= new Geo::Forward;
298 335
299 my $fix = $self->{fix} or return; 336 my $fix = $self->{fix} or return;
300 $fix->{mode} >= 2 or return; 337 $fix->{mode} >= 2 or return;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines