44import time , aenum , threading
55import argparse
66from datetime import datetime
7- import ircreporter
87
98class CSP_adress (aenum .Enum ):
109 ESP = 0
@@ -17,110 +16,31 @@ class CSP_adress(aenum.Enum):
1716 ADCS2 = 6
1817 MCC = 9
1918
20- class Parser (threading .Thread ):
21-
22- DEFAULT_FREQUENCY = 437425000
23- DEFAULT_MODINDEX = 1
24- DEFAULT_BITRATE = 2400
25- DEFAULT_POWER = 26
26- DEFAULT_TRAINING = 200
27- DEFAUL_SYNCWORD = "4f5a34" # OZ4
28-
29- LOGFILE = "log.txt"
19+ class Parser ():
3020
31- def __init__ (self , qth , config , enable_doppler = True , verify_packets = True ,
32- enable_reporting = False ):
33- self .qth = qth
34- self .enable_doppler = enable_doppler
21+ def __init__ (self , verify_packets = False ):
3522 self .verify_packets = verify_packets
36-
37- self .center_freq = Parser .DEFAULT_FREQUENCY
38- self .bb_lock = threading .Lock ()
39- with self .bb_lock :
40- self .bluebox = bluebox .Bluebox ()
41-
42- self .irc = None
43- if enable_reporting :
44- self .irc = ircreporter .IRCReporter ()
45- if self .qth :
46- # Report location of bluebox
47- self .irc .send ("Location: {}" .format (self .qth ))
48- self .config_version = - 1
49- self .config = config
50- self .set_config (self .config .get_config (), True )
51-
52- def set_config (self , config , force_update = False ):
53- with self .bb_lock :
54- if config :
55- if force_update or ('version' in config and config ['version' ] > self .config_version ):
56- settings = config ['radio_settings' ]
57- self .center_freq = settings ['frequency' ] if 'frequency' in settings else DEFAULT_FREQUENCY
58-
59- self .bluebox .set_frequency (self .center_freq )
60- time .sleep (0.01 )
61- self .bluebox .set_modindex (settings ['modindex' ]) if 'modindex' in settings else None
62- time .sleep (0.01 )
63- self .bluebox .set_bitrate (settings ['bitrate' ]) if 'bitrate' in settings else None
64- time .sleep (0.01 )
65- self .bluebox .set_power (settings ['power' ]) if 'power' in settings else None
66- time .sleep (0.01 )
67- self .bluebox .set_training (settings ['training' ]) if 'training' in settings else None
68- time .sleep (0.01 )
69- self .bluebox .set_syncword (int (settings ['syncword' ], 16 )) if 'syncword' in settings else None
70- time .sleep (0.01 )
71-
72- self .config_version = config ['version' ] if 'version' in config else self .config_version
73-
74- elif force_update :
75- # Set default config
76- self .bluebox .set_frequency (Parser .DEFAULT_FREQUENCY )
77- time .sleep (0.01 )
78- self .bluebox .set_modindex (Parser .DEFAULT_MODINDEX )
79- time .sleep (0.01 )
80- self .bluebox .set_bitrate (Parser .DEFAULT_BITRATE )
81- time .sleep (0.01 )
82- self .bluebox .set_power (Parser .DEFAULT_POWER )
83- time .sleep (0.01 )
84- self .bluebox .set_training (Parser .DEFAULT_TRAINING )
85- time .sleep (0.01 )
86- self .bluebox .set_syncword (int (Parser .DEFAULT_SYNCWORD , 16 ))
87-
88- self .config_version = - 1
23+ self .ec = fec .PacketHandler ()
8924
90- @ classmethod
91- def verify_packet (cls , packet ):
25+
26+ def verify_packet (self , packet ):
9227 pass
93-
94- @classmethod
95- def parse_data (cls , bin_data , verify_packets , logfile = None , irc = None ):
96- logmsg = "=================\n "
97- logmsg = "{}\n " .format (datetime .now ().isoformat (' ' ))
98- logmsg += "{}\n " .format (binascii .b2a_hex (bin_data ))
99- if irc :
100- irc .send ("{}" .format (datetime .now ().isoformat (' ' )))
101- irc .send ("{}" .format (binascii .b2a_hex (bin_data )))
28+
29+ def parse_data (self , bin_data ):
30+ data , bit_corr , byte_corr = self .ec .deframe (bin_data )
31+
10232 payload = None
103- if verify_packets :
104- resp = cls .verify_packet (bin_data )
33+ if self . verify_packets :
34+ resp = self .verify_packet (bin_data )
10535 # print resp['status'] - something linke: payload data from ss to ss
10636 # : failed verification
10737 # : beacon packet
10838 # if beacon, extract payload
10939
11040 else :
11141 # Parsing with verification
112- ec = fec .PacketHandler () # for Reed-Solomon codes
113- data , bit_corr , byte_corr = ec .deframe (bin_data )
11442 hexdata = binascii .b2a_hex (data )
115-
116- logmsg += "{}\n {}, {}\n " .format (hexdata , bit_corr , byte_corr )
117- #
118- print ("\n " + "#=" * 40 + "#\n " )
119- print ("Received packet {}" .format (datetime .now ().isoformat (' ' )))
120- print ("Bit corr: {}" .format (bit_corr ))
121- print ("Byte corr: {}" .format (byte_corr ))
122- print ("{}\n " .format (hexdata ))
123-
43+ print hexdata
12444 header = struct .unpack ("<I" , data [0 :4 ])[0 ]
12545 # Parse CSP header
12646 src = ((header >> 25 ) & 0x1f )
@@ -130,90 +50,8 @@ def parse_data(cls, bin_data, verify_packets, logfile=None, irc=None):
13050 if CSP_adress (src ) == CSP_adress .UHF and CSP_adress (dest ) == CSP_adress .MCC and dest_port == 10 :
13151 payload = hexdata [8 :- 4 ]
13252 else :
133- print "Possibly payload data from {0} to {1}. Will not attempt to parse" .format (CSP_adress (src ), CSP_adress (dest ))
53+ raise Exception ( "Possibly payload data from {0} to {1}. Will not attempt to parse" .format (CSP_adress (src ), CSP_adress (dest ) ))
13454
13555 if payload :
13656 beacon_decode = beacon .Beacon (payload )
137- logmsg += "{}\n " .format (beacon_decode )
138- print beacon_decode
139-
140- if logfile :
141- with open (logfile , "a" ) as f :
142- f .write (logmsg )
143-
144-
145- def run (self ):
146- if self .enable_doppler :
147- self .__enable_doppler_correction__ ()
148-
149- while True :
150- try :
151- with self .bb_lock :
152- data , rssi , freq = self .bluebox .receive (1000 )
153- if data :
154- # Parse data
155- packet = Parser .parse_data (data , self .verify_packets ,
156- logfile = Parser .LOGFILE , irc = self .irc )
157- # TODO: Report
158- except Exception as e :
159- print e
160- # Update config if updated
161- # An observer might be more useful
162- config = self .config .get_config ()
163- self .set_config (config )
164-
165- def __enable_doppler_correction__ (self ):
166- qth = (self .qth [0 ], - self .qth [1 ], self .qth [2 ])
167- tle = self .config .get_config ()['tle' ]
168- self .__doppler_correction__ (qth , tle )
169-
170- def __doppler_correction__ (self , qth , tle ):
171- # the predict library expects long (W)
172- # We expect long (E)
173- sat_info = predict .observe (tle , qth )
174- freq = self .center_freq + sat_info ['doppler' ]
175- print "Doppler:" , freq
176- with self .bb_lock :
177- self .bluebox .set_frequency (freq )
178-
179- t = threading .Timer (10 , self .__doppler_correction__ , [qth , tle ])
180- t .daemon = True
181- t .start ()
182-
183- if __name__ == '__main__' :
184- args_parser = argparse .ArgumentParser (description = 'AAUSAT4 Beacon Parser' )
185- args_parser .add_argument ('--lat' , dest = 'lat' , required = False , type = float , default = None ,
186- help = 'Latitude of ground station (N), e.g. 55.6167' )
187- args_parser .add_argument ('--lon' , dest = 'lon' , required = False , type = float , default = None ,
188- help = 'Longitude of ground station (W), e.g. -12.6500' )
189- args_parser .add_argument ('--alt' , dest = 'alt' , required = False , type = float , default = None ,
190- help = 'Altitude of ground station (meters), e.g. 10' )
191- args_parser .add_argument ('--disable-doppler' , dest = 'enable_doppler' ,
192- action = 'store_false' ,
193- required = False ,
194- help = 'Disables doppler tracking.' )
195- args_parser .add_argument ('--enable-reporting' , dest = 'enable_reporting' ,
196- action = 'store_true' ,
197- required = False ,
198- help = 'Enables automatic reporting of received packets.' )
199- args_parser .add_argument ('--hexstr' , dest = 'hexstr' , required = False , default = None ,
200- help = 'Decodes the hex string and exits.' )
201-
202- args = args_parser .parse_args ()
203-
204- if args .hexstr :
205- bin_data = binascii .unhexlify (args .hexstr )
206- Parser .parse_data (bin_data , False , False )
207-
208- elif (not args .enable_doppler ) or (args .lat and args .lon and args .alt ):
209- # Start parser
210- qth = None
211- if args .enable_doppler :
212- qth = (args .lat , args .lon , args .alt )
213- config = config .Config ()
214- parser = Parser (qth , config , enable_doppler = args .enable_doppler ,
215- verify_packets = False , enable_reporting = args .enable_reporting )
216- parser .run ()
217- else :
218- args_parser .print_help ()
219- exit (1 )
57+ return beacon_decode
0 commit comments