[103] | 1 | #!/usr/bin/perl |
---|
| 2 | |
---|
| 3 | use strict; |
---|
| 4 | use Math::Trig; |
---|
| 5 | |
---|
| 6 | my $r = 6371000.785; |
---|
| 7 | my $maptype = "satellite"; |
---|
| 8 | my $weight = 3; |
---|
| 9 | my $zoom = 14; |
---|
| 10 | my $size = "600x600"; |
---|
| 11 | my $sensor = "false"; |
---|
| 12 | my $url = "https://maps.googleapis.com/maps/api/staticmap"; |
---|
| 13 | my $known_flarms = { |
---|
| 14 | "4B0CF5" => "Robin HB-EXP", |
---|
| 15 | "4B1307" => "Bravo HB-HFJ" |
---|
| 16 | }; |
---|
| 17 | my $step_time = 3; |
---|
| 18 | my $timeout = 45; |
---|
| 19 | |
---|
| 20 | my ($from, $until, $before, $now) = (undef, undef, undef, undef); |
---|
| 21 | my ($own_lat, $own_long); |
---|
| 22 | my $flarm = undef; |
---|
| 23 | my $seen; |
---|
| 24 | |
---|
| 25 | sub fstr { |
---|
| 26 | my ($value,$precision) = @_; |
---|
| 27 | $precision ||= 5; |
---|
| 28 | my $s = sprintf("%.${precision}f", $value); |
---|
| 29 | $s =~ s/\.?0*$//; |
---|
| 30 | return $s; |
---|
| 31 | } |
---|
| 32 | |
---|
| 33 | |
---|
| 34 | sub parse_GPGGA { |
---|
| 35 | my ($line) = @_; |
---|
| 36 | my ($msg,$time,$lat,$northsouth,$long,$eastwest,$quality,$satelites,$dhop,$alt) = split(/,/, $line); |
---|
| 37 | my ($g_lat, $g_long) = nmeaToGoogle($lat,$northsouth,$long,$eastwest); |
---|
| 38 | print "nmea: " . $lat . $northsouth . "," . $long . $eastwest . "\n"; |
---|
| 39 | print "google: " . $g_lat . "," . $g_long . "\n"; |
---|
| 40 | $now = $time; |
---|
| 41 | $own_lat = $g_lat; |
---|
| 42 | $own_long = $g_long; |
---|
| 43 | } |
---|
| 44 | |
---|
| 45 | sub parse_PFLAA { |
---|
| 46 | my ($line) = @_; |
---|
| 47 | my ($msg,$alarm,$rel_north,$rel_east,$rel_vert,$id_type,$id,$track,$turnrate,$groundspeed,$climb,$type) = split(/,/, $line); |
---|
| 48 | return unless (defined($now)); |
---|
| 49 | return if (defined($from) && $now < $from); |
---|
| 50 | return if (defined($until) && $now > $until); |
---|
| 51 | return if (defined($flarm) && $id ne $flarm); |
---|
| 52 | return unless (defined($own_lat)); |
---|
| 53 | return unless (defined($own_long)); |
---|
| 54 | return unless ($groundspeed > 10 || $rel_vert > 20); |
---|
| 55 | |
---|
| 56 | print $now . ": " . $line . " " . ($own_lat+distToLat($rel_north)) . "," . ($own_long+distToLong($rel_east)) . "\n"; |
---|
| 57 | store($now, $id, $own_lat + distToLat($rel_north), $own_long + distToLong($rel_east)); |
---|
| 58 | } |
---|
| 59 | |
---|
| 60 | sub store { |
---|
| 61 | my ($time, $id, $g_lat, $g_long) = @_; |
---|
| 62 | |
---|
| 63 | if (!exists($seen->{$id})) { |
---|
| 64 | $seen->{$id} = (); |
---|
| 65 | } |
---|
| 66 | if (!defined($before) || $now >= $before+$step_time) { |
---|
| 67 | $before = $now; |
---|
| 68 | push(@{$seen->{$id}}, [$time, $g_lat, $g_long]); |
---|
| 69 | } |
---|
| 70 | } |
---|
| 71 | |
---|
| 72 | sub distToLat { |
---|
| 73 | my ($dist) = @_; |
---|
| 74 | return 180*$dist/($r*pi); |
---|
| 75 | } |
---|
| 76 | |
---|
| 77 | sub distToLong { |
---|
| 78 | my ($dist) = @_; |
---|
| 79 | return 180*$dist/(cos($own_lat*pi/180)*$r*pi); |
---|
| 80 | } |
---|
| 81 | |
---|
| 82 | sub nmeaToGoogle { |
---|
| 83 | my ($lat,$northsouth,$long,$eastwest) = @_; |
---|
| 84 | my $lat_sign = ($northsouth =~ /N/) ? 1 : -1; |
---|
| 85 | $lat =~ /^(\d{2})(\d{2})\.(\d{5})$/; |
---|
| 86 | my $g_lat = ($1 + ($2 + $3*1e-5)/60) * $lat_sign; |
---|
| 87 | |
---|
| 88 | my $long_sign = ($eastwest =~ /E/) ? 1 : -1; |
---|
| 89 | $long =~ /^(\d{3})(\d{2})\.(\d{5})$/; |
---|
| 90 | my $g_long = ($1 + ($2 + $3*1e-5)/60) * $long_sign; |
---|
| 91 | return ($g_lat, $g_long); |
---|
| 92 | } |
---|
| 93 | |
---|
| 94 | while (my $line = <>) { |
---|
| 95 | chomp($line); |
---|
| 96 | ($line =~ /^\$GPGGA/) && parse_GPGGA($line); |
---|
| 97 | ($line =~ /^\$PFLAA/) && parse_PFLAA($line); |
---|
| 98 | } |
---|
| 99 | |
---|
| 100 | foreach my $flarm_id (keys(%{$seen})) { |
---|
| 101 | my $plane = exists($known_flarms->{$flarm_id}) ? $known_flarms->{$flarm_id} : "???"; |
---|
| 102 | print "==== Flarm-ID: $flarm_id ($plane) ====\n"; |
---|
| 103 | |
---|
| 104 | my $last_record; |
---|
| 105 | foreach my $record (@{$seen->{$flarm_id}}) { |
---|
| 106 | my ($time, $g_lat, $g_long) = @{$record}; |
---|
| 107 | |
---|
| 108 | if (!defined($last_record) || $time >= $last_record + $timeout) { |
---|
| 109 | print "\n"; |
---|
| 110 | print $url |
---|
| 111 | . "?maptype=" . $maptype |
---|
| 112 | . "&zoom=" . $zoom |
---|
| 113 | . "&size=" . $size |
---|
| 114 | . "&sensor=" . $sensor |
---|
| 115 | . "¢er=" . fstr($own_lat, 5) . "," . fstr($own_long, 5) |
---|
| 116 | . "&path=color:red|weight:3"; |
---|
| 117 | } |
---|
| 118 | $last_record = $time; |
---|
| 119 | print "|".fstr($g_lat,5) . "," . fstr($g_long, 5); |
---|
| 120 | } |
---|
| 121 | $last_record = undef; |
---|
| 122 | print "\n\n"; |
---|
| 123 | } |
---|
| 124 | |
---|
| 125 | |
---|