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

Comparing GPS/GPS.pm (file contents):
Revision 1.3 by root, Fri Apr 26 21:53:14 2002 UTC vs.
Revision 1.4 by stefan, Sun Apr 28 09:05:10 2002 UTC

1package GPS; 1package GPS;
2 2
3use strict; 3use strict;
4use warnings; 4use warnings;
5use POSIX (); 5use POSIX ();
6use Coro::Socket; 6use IO::Socket::INET;
7 7
8our $VERSION = 0.01; 8our $VERSION = 0.01;
9
10
9 11
10sub new { 12sub new {
11 my ($class, %arg) = @_; 13 my ($class, %arg) = @_;
12 $arg{port} ||= 2947; 14 $arg{port} ||= 2947;
13 $arg{host} ||= 'localhost'; 15 $arg{host} ||= 'localhost';
14 16
17 print "$class\n";
18 my $m = $class =~ /Raw$/ ? 'Coro::Socket' : 'IO::Socket::INET';
15 my $sock = new Coro::Socket PeerHost => $arg{host}, PeerPort => $arg{port} 19 my $sock = new $m PeerHost => $arg{host}, PeerPort => $arg{port}
20
16 or die 'GPSD ($arg{host}:$arg{port}): $!'; 21 or die 'GPSD ($arg{host}:$arg{port}): $!';
17 print $sock "HELO\n"; 22 print $sock "HELO\n";
18 <$sock> =~ /GPSD/ or die 'no GPSD'; 23 <$sock> =~ /GPSD/ or die 'no GPSD';
24 if($class =~/Raw$/) {
25 print $sock "R\n";
26 <$sock> =~ /GPSD,R=1/ or die "can't enable raw-mode";
27 }
19 28
20 bless { 29 bless {
21 fh => $sock, 30 fh => $sock,
22 minpoll => $arg{minpoll} || 1, 31 minpoll => $arg{minpoll} || 1,
23 last => 0, 32 last => 0,
24 data => {} 33 data => {},
25 }, $class; 34 }, $class;
26} 35}
27 36
28sub poll { 37sub poll {
29 my $self = shift; 38 my $self = shift;
30 39
31 print {$self->{fh}} "dpva\n"; 40 print {$self->{fh}} "dpva\n";
32 41
33 if ($self->{fh}->readline =~ m%GPSD,D=(\d\d)/(\d\d)/(\d\d\d\d) (\d\d):(\d\d):(\d\d),P=([\-0-9.]+) ([\-0-9.]+),V=([0-9.]+),A=([\-0-9.]+)%) { 42 if (readline ($self->{fh}) =~ m%GPSD,D=(\d\d)/(\d\d)/(\d\d\d\d) (\d\d):(\d\d):(\d\d),P=([\-0-9.]+) ([\-0-9.]+),V=([0-9.]+),A=([\-0-9.]+)%) {
34 local $ENV{TZ} = "+0000"; 43 local $ENV{TZ} = "+0000";
35 $self->{data} = { 44 $self->{data} = {
36 time => (POSIX::mktime $6,$5,$4,$2,$1-1,$3-1900,0,0), 45 time => (POSIX::mktime $6,$5,$4,$2,$1-1,$3-1900,0,0),
37 lat => $7, 46 lat => $7,
38 long => $8, 47 long => $8,
46sub data { 55sub data {
47 $_[0]->poll if time - $_[0]{last} >= $_[0]{minpoll}; 56 $_[0]->poll if time - $_[0]{last} >= $_[0]{minpoll};
48 $_[0]{data}; 57 $_[0]{data};
49} 58}
50 59
60package GPS::Raw;
61our @ISA = qw(GPS);
62use strict;
63use warnings;
64use POSIX qw(modf);
65use Coro::Socket;
66use Coro::Event;
67use Coro;
68
69sub PI { 3.14159265 } # not used :)
70
71sub latlon($$) {
72 my ($t1,$t2) = modf($_[0] / 100);
73 $t2 = $t2 + $t1*100 / 60;
74 $t2 *= -1 if $_[1] =~ /[SW]/i;
75 $t2
76}
77
78our %cbs = ( 'GPGLL' => sub { my ($res, @a) = @_;
79 $res->{Plain}{Latitude} = $a[0];
80 $res->{lat} = latlon $a[0], $a[1];
81 $res->{Plain}{NS} = $a[1];
82 $res->{Plain}{Longitude} = $a[2];
83 $res->{long} = latlon $a[2], $a[3];
84 $res->{Plain}{WE} = $a[3];
85 $res->{Plain}{UTC} = $a[4];
86 },
87 'PGRMZ' => sub { my ($res, @a) = @_;
88 $res->{Plain}{Altitude} = $a[0];
89 $res->{alt} = $a[0] / 3.2808399; # foot -> meters
90 },
91 'GPRMC' => sub { my ($res, @a) = @_;
92 $res->{Plain}{Speed} = $a[6];
93 $res->{v} = $a[6] * 1.852; # knoten :)
94 $res->{Plain}{Course} = $a[7];
95 $res->{course} = $a[7];
96 },
97 'GPRMB' => sub { my ($res, @a) = @_;
98 $res->{WP}{origin} = $a[2];
99 $res->{WP}{destination} = $a[3];
100 $res->{WP}{destination} = $a[4];
101 $res->{WP}{desLat} = latlon $a[5], $a[6];
102 $res->{WP}{desLong} = latlon $a[7], $a[8];
103 $res->{WP}{distance} = $a[9]* 1.852; #seemeilen -> km
104 $res->{WP}{bearing} = $a[10];
105 $res->{WP}{speed} = $a[11] *1852; #knoten->km/h
106
107 },
108 );
109
110
111sub _chksum($) {
112 my ($line,$cs) = (shift,0);
113 $line =~ m/\$([^\*]+)\*([0-9A-F]{2})$/ or do {
114 warn "illegal line \"$line\"";
115 return 0;
116 };
117 my ($str, $pcs) = ($1, $2);
118 map {$cs ^= $_} unpack ("C*", $str);
119 return 1 if $cs == hex($pcs);
120 warn "illegal checksum. packet=$pcs computed=$cs";
121 return 0;
122}
123
124sub get_line($) {
125 my $sock = $_[0]{fh};
126cserr:
127 my $l = readline $sock;
128 $l =~ s/[\015\012\0]*//g;
129 _chksum($l) or goto cserr;
130 warn "unknown line \"$l\"" unless $l =~ /^\$([^,]+),([^\*]+)\*[A-F0-9]{2}$/;
131 my ($cmd, $arg) = ($1,$2);
132 ($l, $cmd, $arg);
133}
134
135sub daemon($) {
136 my $self = shift;
137 async {
138 my $self = shift;
139 my $res = $self->{data};
140 use Data::Dumper;
141 $res->{lines} = 0;
142 while(1) {
143 my($line, $cmd, $arg) = $self->get_line;
144 $res->{lines}++;
145 $res->{Raw}{$cmd} = $arg;
146 &{$cbs{$cmd}}($res, split /,/, $arg) if exists $cbs{$cmd};
147 }
148 } $self;
149}
150
151sub data {
152 cede;
153 $_[0]{data};
154}
155
511; 1561;
52 157

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines