diff --git a/pyModeS/streamer/modeslive b/pyModeS/streamer/modeslive index d16724b..040f0ca 100755 --- a/pyModeS/streamer/modeslive +++ b/pyModeS/streamer/modeslive @@ -24,6 +24,7 @@ parser.add_argument('--port', help='raw data port', required=True) parser.add_argument('--rawtype', help='beast, avr or skysense', required=True) parser.add_argument('--latlon', help='receiver position', nargs=2, metavar=('LAT', 'LON'), required=True) parser.add_argument('--show-uncertainty', dest='uncertainty', help='display uncertaint values, default off', action='store_true', required=False, default=False) +parser.add_argument('--dumpto', help='folder to dump decoded output', required=False, default=None) args = parser.parse_args() SERVER = args.server @@ -32,6 +33,11 @@ RAWTYPE = args.rawtype LAT0 = float(args.latlon[0]) LON0 = float(args.latlon[1]) UNCERTAINTY = args.uncertainty +DUMPTO = os.getcwd() + '/' + args.dumpto + +if not os.path.isdir(DUMPTO): + print('Error: dump folder (%s) does not exist' % DUMPTO) + sys.exit(1) class ModesClient(BaseClient): @@ -75,7 +81,7 @@ client = ModesClient(host=SERVER, port=PORT, rawtype=RAWTYPE) client.daemon = True client.start() -stream = Stream(lat0=LAT0, lon0=LON0) +stream = Stream(lat0=LAT0, lon0=LON0, dumpto=DUMPTO) try: screen = Screen(uncertainty=UNCERTAINTY) diff --git a/pyModeS/streamer/stream.py b/pyModeS/streamer/stream.py index c10dd15..ecc255e 100644 --- a/pyModeS/streamer/stream.py +++ b/pyModeS/streamer/stream.py @@ -1,16 +1,15 @@ from __future__ import absolute_import, print_function, division -import numpy as np +import os import time +import datetime +import csv import pyModeS as pms class Stream(): - def __init__(self, lat0, lon0): + def __init__(self, lat0, lon0, dumpto=None): self.acs = dict() - self.cache_new_acs = False - self.__new_acs = set() - self.lat0 = lat0 self.lon0 = lon0 @@ -18,6 +17,12 @@ class Stream(): self.cache_timeout = 60 # seconds + if dumpto is not None and os.path.isdir(dumpto): + self.dumpto = dumpto + else: + self.dumpto = None + + def process_raw(self, adsb_ts, adsb_msgs, commb_ts, commb_msgs, tnow=None): """process a chunk of adsb and commb messages recieved in the same time period. @@ -28,6 +33,7 @@ class Stream(): self.t = tnow local_updated_acs_buffer = [] + output_buffer = [] # process adsb message for t, msg in zip(adsb_ts, adsb_msgs): @@ -70,7 +76,9 @@ class Stream(): self.acs[icao]['live'] = int(t) if 1 <= tc <= 4: - self.acs[icao]['call'] = pms.adsb.callsign(msg) + cs = pms.adsb.callsign(msg) + self.acs[icao]['call'] = cs + output_buffer.append(['%.07f'%t, icao, 'cs', cs]) if (5 <= tc <= 8) or (tc == 19): vdata = pms.adsb.velocity(msg) @@ -88,6 +96,11 @@ class Stream(): self.acs[icao]['roc'] = roc self.acs[icao]['tv'] = t + output_buffer.append(['%.07f'%t, icao, 'gs', spd]) + output_buffer.append(['%.07f'%t, icao, 'trk', trk]) + output_buffer.append(['%.07f'%t, icao, 'roc', roc]) + + if (5 <= tc <= 18): oe = pms.adsb.oe_flag(msg) self.acs[icao][oe] = msg @@ -119,7 +132,14 @@ class Stream(): self.acs[icao]['tpos'] = t self.acs[icao]['lat'] = latlon[0] self.acs[icao]['lon'] = latlon[1] - self.acs[icao]['alt'] = pms.adsb.altitude(msg) + + alt = pms.adsb.altitude(msg) + self.acs[icao]['alt'] = alt + + output_buffer.append(['%.07f'%t, icao, 'lat', latlon[0]]) + output_buffer.append(['%.07f'%t, icao, 'lon', latlon[1]]) + output_buffer.append(['%.07f'%t, icao, 'alt', alt]) + local_updated_acs_buffer.append(icao) # Uncertainty & accuracy @@ -166,31 +186,48 @@ class Stream(): bds = pms.bds.infer(msg) if bds == 'BDS50': - tas = pms.commb.tas50(msg) - roll = pms.commb.roll50(msg) - rtrk = pms.commb.rtrk50(msg) + roll50 = pms.commb.roll50(msg) + trk50 = pms.commb.trk50(msg) + rtrk50 = pms.commb.rtrk50(msg) + gs50 = pms.commb.gs50(msg) + tas50 = pms.commb.tas50(msg) self.acs[icao]['t50'] = t - if tas: - self.acs[icao]['tas'] = tas - if roll: - self.acs[icao]['roll'] = roll - if rtrk: - self.acs[icao]['rtrk'] = rtrk + if tas50: + self.acs[icao]['tas'] = tas50 + output_buffer.append(['%.07f'%t, icao, 'tas50', tas50]) + if roll50: + self.acs[icao]['roll'] = roll50 + output_buffer.append(['%.07f'%t, icao, 'roll50', roll50]) + if rtrk50: + self.acs[icao]['rtrk'] = rtrk50 + output_buffer.append(['%.07f'%t, icao, 'rtrk50', rtrk50]) + + if trk50: + output_buffer.append(['%.07f'%t, icao, 'trk50', trk50]) + if gs50: + output_buffer.append(['%.07f'%t, icao, 'gs50', gs50]) elif bds == 'BDS60': - ias = pms.commb.ias60(msg) - hdg = pms.commb.hdg60(msg) - mach = pms.commb.mach60(msg) + ias60 = pms.commb.ias60(msg) + hdg60 = pms.commb.hdg60(msg) + mach60 = pms.commb.mach60(msg) + roc60baro = pms.commb.vr60baro(msg) + roc60ins = pms.commb.vr60ins(msg) - if ias or hdg or mach: + if ias60 or hdg60 or mach60: self.acs[icao]['t60'] = t - if ias: - self.acs[icao]['ias'] = ias - if hdg: - self.acs[icao]['hdg'] = hdg - if mach: - self.acs[icao]['mach'] = mach + if ias60: + self.acs[icao]['ias'] = ias60 + if hdg60: + self.acs[icao]['hdg'] = hdg60 + if mach60: + self.acs[icao]['mach'] = mach60 + + if roc60baro: + output_buffer.append(['%.07f'%t, icao, 'roc60baro', roc60baro]) + if roc60ins: + output_buffer.append(['%.07f'%t, icao, 'roc60ins', roc60ins]) # clear up old data for icao in list(self.acs.keys()): @@ -198,8 +235,12 @@ class Stream(): del self.acs[icao] continue - if self.cache_new_acs: - self.add_new_aircraft(local_updated_acs_buffer) + if self.dumpto is not None: + dh = str(datetime.datetime.now().strftime("%Y%m%d_%H")) + fn = self.dumpto + '/pymodes_dump_%s.csv' % dh + with open(fn, "a") as f: + writer = csv.writer(f) + writer.writerows(output_buffer) return @@ -211,20 +252,3 @@ class Stream(): if acs[icao]['lat'] is None: acs.pop(icao) return acs - - def add_new_aircraft(self, acs): - """add new aircraft to the list""" - self.__new_acs.update(acs) - return - - def get_new_aircraft(self): - """update aircraft from last iteration""" - newacs = dict() - for ac in self.__new_acs: - if ac in self.acs: - newacs[ac] = self.acs[ac] - return newacs - - def reset_new_aircraft(self): - """reset the updated icao buffer once been read""" - self.__new_acs = set()