… | |
… | |
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 | =item on_fix => $cb->({point}) |
96 | =item on_fix => $cb->({point}) |
97 | |
97 | |
98 | Called regularly. The C<{point}> hash contains at least the following |
98 | Called regularly (usually about once/second), even when there is no |
99 | members: |
99 | connection to the GPSD (so is useful to update your idea of the current |
|
|
100 | position). The passed hash reference must I<not> be modified in any way. |
|
|
101 | |
|
|
102 | If C<mode> is C<2> or C<3>, then the C<{point}> hash contains at least the |
|
|
103 | following members, otherwise it is undefined which members exist. Members |
|
|
104 | whose values are not known are C<undef> (usually the error values, speed |
|
|
105 | and so on). |
100 | |
106 | |
101 | time when this fix was received (s) |
107 | time when this fix was received (s) |
102 | |
108 | |
103 | lat latitude (S -90..90 N) |
109 | lat latitude (S -90..90 N) |
104 | lon longitude (W -180..180 E) |
110 | lon longitude (W -180..180 E) |
… | |
… | |
122 | |
128 | |
123 | sub new { |
129 | sub new { |
124 | my $class = shift; |
130 | my $class = shift; |
125 | my $self = bless { |
131 | my $self = bless { |
126 | @_, |
132 | @_, |
|
|
133 | interval => 1, |
|
|
134 | fix => { time => AnyEvent->now, mode => 1 }, |
127 | }, $class; |
135 | }, $class; |
128 | |
136 | |
|
|
137 | $self->interval_timer; |
129 | $self->connect; |
138 | $self->connect; |
130 | |
139 | |
131 | $self |
140 | $self |
132 | } |
141 | } |
133 | |
142 | |
… | |
… | |
148 | Scalar::Util::weaken $self; |
157 | Scalar::Util::weaken $self; |
149 | $self->{retry_w} = AnyEvent->timer (after => 1, cb => sub { |
158 | $self->{retry_w} = AnyEvent->timer (after => 1, cb => sub { |
150 | delete $self->{retry_w}; |
159 | delete $self->{retry_w}; |
151 | $self->connect; |
160 | $self->connect; |
152 | }); |
161 | }); |
|
|
162 | } |
|
|
163 | |
|
|
164 | # make sure we send "no fix" updates when we lose connectivity |
|
|
165 | sub interval_timer { |
|
|
166 | my ($self) = @_; |
|
|
167 | |
|
|
168 | $self->{interval_w} = AnyEvent->timer (after => $self->{interval}, cb => sub { |
|
|
169 | if (AnyEvent->now - $self->{fix}{time} > $self->{interval} * 1.9) { |
|
|
170 | $self->{fix}{mode} = 1; |
|
|
171 | $self->event (fix => $self->{fix}); |
|
|
172 | } |
|
|
173 | |
|
|
174 | $self->interval_timer; |
|
|
175 | }); |
|
|
176 | |
|
|
177 | Scalar::Util::weaken $self; |
153 | } |
178 | } |
154 | |
179 | |
155 | sub connect { |
180 | sub connect { |
156 | my ($self) = @_; |
181 | my ($self) = @_; |
157 | |
182 | |
… | |
… | |
177 | on_error => sub { |
202 | on_error => sub { |
178 | $self->event ("error"); |
203 | $self->event ("error"); |
179 | $self->retry; |
204 | $self->retry; |
180 | }, |
205 | }, |
181 | on_eof => sub { |
206 | on_eof => sub { |
182 | $! = &Errno::EBADMSG; |
207 | $! = &Errno::EPIPE; |
183 | $self->event ("error"); |
208 | $self->event ("error"); |
184 | $self->retry; |
209 | $self->retry; |
185 | }, |
210 | }, |
186 | on_read => sub { |
211 | on_read => sub { |
187 | $_[0]{rbuf} =~ s/^([^\015\012]*)\015\012// |
212 | $_[0]{rbuf} =~ s/^([^\015\012]*)\015\012// |
… | |
… | |
192 | ; |
217 | ; |
193 | |
218 | |
194 | $self->send ("w"); |
219 | $self->send ("w"); |
195 | $self->send ("o"); |
220 | $self->send ("o"); |
196 | $self->send ("y"); |
221 | $self->send ("y"); |
|
|
222 | $self->send ("c"); |
197 | |
223 | |
198 | $self->event ("connect"); |
224 | $self->event ("connect"); |
199 | } else { |
225 | } else { |
200 | $self->event ("error"); |
226 | $self->event ("error"); |
201 | } |
227 | } |
… | |
… | |
235 | |
261 | |
236 | $self->{state}{$type} = [$data => $self->{now}]; |
262 | $self->{state}{$type} = [$data => $self->{now}]; |
237 | |
263 | |
238 | if ($type eq "O") { |
264 | if ($type eq "O") { |
239 | my @data = split /\s+/, $data; |
265 | my @data = split /\s+/, $data; |
|
|
266 | |
|
|
267 | my $fix = $self->{fix}; |
|
|
268 | |
240 | my %fix = (time => $self->{now}); |
269 | $fix->{time} = $self->{now}; |
241 | |
270 | |
242 | if (@data > 3) { |
271 | if (@data > 3) { |
243 | # the gpsd time is virtually useless as it is truncated :/ |
272 | # 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); |
273 | for (qw(tag _time _terr lat lon alt herr verr bearing speed vspeed berr serr vserr mode)) { |
|
|
274 | $type = shift @data; |
|
|
275 | $fix->{$_} = $type eq "?" ? undef : $type; |
|
|
276 | } |
245 | |
277 | |
246 | $fix{mode} = 2 if $fix{mode} eq "?"; # arbitrary choice |
278 | $fix->{mode} = 2 if $fix->{mode} eq "?"; # arbitrary choice |
247 | } else { |
279 | } else { |
248 | $fix{mode} = 1; |
280 | $fix->{mode} = 1; |
249 | } |
281 | } |
250 | |
282 | |
251 | $self->{fix} = \%fix; |
|
|
252 | $self->event (fix => \%fix); |
283 | $self->event (fix => $fix); |
253 | |
284 | |
254 | } elsif ($type eq "Y") { |
285 | } elsif ($type eq "Y") { |
255 | my (undef, @sats) = split /:/, $data; |
286 | my (undef, @sats) = split /:/, $data; |
256 | |
287 | |
257 | $self->{satellite_info} = [map { |
288 | $self->{satellite_info} = [map { |
… | |
… | |
264 | fix => $sat[4], |
295 | fix => $sat[4], |
265 | } |
296 | } |
266 | } @sats]; |
297 | } @sats]; |
267 | |
298 | |
268 | $self->event (satellite_update => $self->{satellite_info}); |
299 | $self->event (satellite_update => $self->{satellite_info}); |
|
|
300 | |
|
|
301 | } elsif ($type eq "C") { |
|
|
302 | $self->{interval} = $data >= 1 ? $data * 1 : 1; |
269 | } |
303 | } |
270 | |
304 | |
271 | # we (wrongly) assume that gpsd responses are always in response |
305 | # we (wrongly) assume that gpsd responses are always in response |
272 | # to an earlier command |
306 | # to an earlier command |
273 | |
307 | |