… | |
… | |
88 | |
88 | |
89 | C<snr> contains the signal strength in decibals (28+ is usually the |
89 | C<snr> contains the signal strength in decibals (28+ is usually the |
90 | minimum value for a good fix). |
90 | minimum value for a good fix). |
91 | |
91 | |
92 | C<fix> contains either C<1> to indicate that this satellite was used for |
92 | C<fix> contains either C<1> to indicate that this satellite was used for |
93 | the last position fix, C<0> otherwise. EGNOS/WAAS etc. satellites will |
93 | the last position fix, C<0> otherwise. EGNOS/WAAS etc. satellites will |
94 | always show as C<0>, even if their correction info was used. |
94 | always show as C<0>, even if their correction info was used. |
95 | |
95 | |
|
|
96 | The passed hash references are read-only. |
|
|
97 | |
96 | =item on_fix => $cb->({point}) |
98 | =item on_fix => $cb->({point}) |
97 | |
99 | |
98 | Called regularly. The C<{point}> hash contains at least the following |
100 | Called regularly (usually about once/second), even when there is no |
99 | members: |
101 | connection to the GPSD (so is useful to update your idea of the current |
|
|
102 | position). The passed hash reference must I<not> be modified in any way. |
|
|
103 | |
|
|
104 | If C<mode> is C<2> or C<3>, then the C<{point}> hash contains at least the |
|
|
105 | following members, otherwise it is undefined which members exist. Members |
|
|
106 | whose values are not known are C<undef> (usually the error values, speed |
|
|
107 | and 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 | |
123 | sub new { |
131 | sub 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 |
|
|
167 | sub 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 | |
155 | sub connect { |
182 | sub 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 | |
… | |
… | |
282 | This returns an estimate of the current position based on the last fix and |
318 | This returns an estimate of the current position based on the last fix and |
283 | the time passed since then. Useful for interactive applications where you |
319 | the time passed since then. Useful for interactive applications where you |
284 | want more frequent updates, but not very useful to store, as the next fix |
320 | want more frequent updates, but not very useful to store, as the next fix |
285 | might well be totally off. |
321 | might well be totally off. |
286 | |
322 | |
287 | If the fix is older then C<$max_seconds> (default: C<1.9>) or if no fix is |
323 | If the fix is older then C<$max_seconds> (default: C<1.9> times the update |
288 | available, returns the empty list. |
324 | interval, i.e. usually C<1.9> seconds) or if no fix is available, returns |
|
|
325 | the empty list. |
289 | |
326 | |
290 | =cut |
327 | =cut |
291 | |
328 | |
292 | sub estimate { |
329 | sub 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; |