allow norad keps to be translated
[spider.git] / perl / convkeps.pl
1 #!/usr/bin/perl -w
2 #
3 # Convert an Amsat 2 line keps bull into Sun.pm format
4 #
5 # This program will accept on stdin a standard AMSAT 2 line keps
6 # bull such as you would find in an email or from the packet network
7 #
8 # It will write a file called /spider/local/Keps.pm, this means that
9 # the latest version will be read in every time you restart the 
10 # cluster.pl. You can also call Sun::load from a cron line if
11 # you like to re-read it automatically. If you update it manually
12 # load/keps will load the latest version into the cluster
13 #
14 # This program is designed to be called from /etc/aliases or
15 # a .forward file so you can get yourself on the keps mailing
16 # list from AMSAT and have the keps updated automatically once
17 # a week.
18 #
19 # I will distribute the latest keps with every patch but you can
20 # get your own data from: 
21 #
22 # http://www.amsat.org/amsat/ftp/keps/current/nasa.all
23 #
24 # Please note that this will UPDATE your keps file
25
26 # Usage: 
27 #    email | convkeps.pl        (in amsat email format)  
28 #    convkeps.pl -p keps.in     (a file with just plain keps)
29
30 # if you add the -c flag then the %keps hash will be cleared down
31 # before adding the new ones.
32 #
33 # Copyright (c) 2000 Dirk Koopman G1TLH
34 #
35 # $Id$
36 #
37
38 require 5.004;
39 package Sun;
40
41 # search local then perl directories
42 BEGIN {
43         # root of directory tree for this system
44         $root = "/spider"; 
45         $root = $ENV{'DXSPIDER_ROOT'} if $ENV{'DXSPIDER_ROOT'};
46         
47         unshift @INC, "$root/perl";     # this IS the right way round!
48         unshift @INC, "$root/local";
49 }
50
51 use strict;
52 use vars qw($root %keps);
53
54 use Data::Dumper;
55 require Keps;
56
57 my $fn = "$root/local/Keps.pm";
58 my $state = 0;
59 my $name;
60 my $ref;
61 my $line;
62 my $count = 0;
63
64 my %lookup = (
65         'AO-5' => 'AO-05',
66         'AO-6' => 'AO-06',
67         'AO-7' => 'AO-07',
68         'AO-8' => 'AO-08',
69         
70 );
71
72 my $f = \*STDIN;
73
74 while (@ARGV) {
75         my $arg = shift @ARGV;
76         if ($arg eq '-p') {
77                 $state = 1;
78         } elsif ($arg eq '-e') {
79                 $state = 0;
80         } elsif ($arg eq '-c') {
81                 %keps = ();
82         } elsif ($arg =~ /^-/) {
83                 die "Usage: convkeps.pl [-c] [-e|-p] [<filename>]\n\t-p - plain file just containing keps\n\t-e - amsat email format input file (default)\n\t-c - clear Keps data before adding this lot\n";
84         } else {
85                 open (IN, $arg) or die "cannot open $arg (!$)";
86                 $f = \*IN;
87         }
88 }
89
90 while (<$f>) {
91         ++$line;
92 #    print;
93         chomp;
94         last if m{^-};
95
96         s/^\s+//;
97     s/[\s\r]+$//;
98         next unless $_;
99         last if m{^/EX}i;
100         
101         if ($state == 0 && /^Decode/i) {
102                 $state = 1;
103         } elsif ($state == 1) {
104                 last if m{^-};
105                 next if m{^To\s+all}i;
106                 
107                 if (/^([- \w]+)(?:\s+\[[-+\w]\])$/) {
108                         my $n = uc $1;
109                         $n =~ s/\s/-/g;
110                         $name = $lookup{$n};
111                         $name ||= $n;
112                         $ref = $keps{$name} = {}; 
113                         $state = 2;
114                 }
115         } elsif ($state == 2) {
116                 if (/^1 /) {
117                         my ($id, $number, $epoch, $decay, $mm2, $bstar, $elset) = unpack "xxa5xxa5xxxa15xa10xa8xa8xxxa4x", $_;
118                         $ref->{id} = $id - 0;
119                         $ref->{number} = $number - 0;
120                         $ref->{epoch} = $epoch - 0;
121                         $ref->{mm1} = $decay - 0;
122                         $ref->{mm2} = genenum($mm2);
123                         $ref->{bstar} = genenum($bstar);
124                         $ref->{elset} = $elset - 0;
125                         #print "$id $number $epoch $decay $mm2 $bstar $elset\n"; 
126                         #print "mm2: $ref->{mm2} bstar: $ref->{bstar}\n";
127                         
128                         $state = 3;
129                 } else {
130                         #print "out of order on line $line\n";
131                         undef $ref;
132                         delete $keps{$name};
133                         $state = 1;
134                 }
135         } elsif ($state == 3) {
136                 if (/^2 /) {
137                         my ($id, $incl, $raan, $ecc, $peri, $man, $mmo, $orbit) = unpack "xxa5xa8xa8xa7xa8xa8xa11a5x", $_;
138                         $ref->{meananomaly} = $man - 0;
139                         $ref->{meanmotion} = $mmo - 0;
140                         $ref->{inclination} = $incl - 0;
141                         $ref->{eccentricity} = ".$ecc" - 0;
142                         $ref->{argperigee} = $peri - 0;
143                         $ref->{raan} = $raan - 0;
144                         $ref->{orbit} = $orbit - 0;
145                         $count++;
146                 } else {
147                         #print "out of order on line $line\n";
148                         delete $keps{$name};
149                 }
150                 undef $ref;
151                 $state = 1;
152         }
153 }
154
155 if ($count) {
156         my $dd = new Data::Dumper([\%keps], [qw(*keps)]);
157         $dd->Indent(1);
158         $dd->Quotekeys(0);
159         open(OUT, ">$fn") or die "$fn $!";
160         print OUT "#\n# this file is automatically produced by convkeps.pl\n#\n";
161         print OUT "# Last update: ", scalar gmtime, "\n#\n";
162         print OUT "\npackage Sun;\n\n";
163         print OUT $dd->Dumpxs;
164         print OUT "1;\n";
165         close(OUT);
166 }
167
168 print "$count keps converted\n";
169 exit($count ? 0 : -1);
170
171
172 # convert (+/-)00000-0 to (+/-).00000e-0
173 sub genenum
174 {
175         my ($sign, $frac, $esign, $exp) = unpack "aa5aa", shift;
176         $esign = '+' if $esign eq ' ';
177         my $n = $sign . "." . $frac . 'e' . $esign . $exp;
178         return $n - 0;
179 }
180