diff --git a/README.rst b/README.rst index e082a2d..63578b0 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,7 @@ The Python Mode-S Decoder (2.0-dev) Python library for Mode-S message decoding. Support Downlink Formats (DF) are: -**Automatic Dependent Surveillance - Broadcast (ADS-B) (DF17)** +**Automatic Dependent Surveillance - Broadcast (ADS-B) (DF 17/18)** - TC=1-4 / BDS 0,8: Aircraft identification and category - TC=5-8 / BDS 0,6: Surface position @@ -40,7 +40,7 @@ New features in v2.0 --------------------- - New structure of the libraries - ADS-B and Comm-B data streaming -- Active aircraft viewing (terminal cursor) +- Active aircraft viewing (terminal curses) - Improved BDS identification - Optimizing decoding speed @@ -65,6 +65,28 @@ To install latest development version (dev-2.0) from the GitHub: pip install git+https://github.com/junzis/pyModeS + +Live view traffic (pmslive) +---------------------------------------------------- +Supports **Mode-S Beast** and **AVR** raw stream + +:: + + pmslive --server [server_address] --port [tcp_port] --rawtype [beast_or_avr] --latlon [lat] [lon] + + Arguments: + -h, --help show this help message and exit + --server SERVER server address or IP + --port PORT raw data port + --rawtype RAWTYPE beast or avr + --latlon LAT LON receiver position + + +Example screen shot: + +.. image:: https://github.com/junzis/pyModeS/raw/master/doc/pmslive-screenshot.png + :width: 700px + Use the library --------------- @@ -147,18 +169,20 @@ Common Mode-S functions pms.icao(msg) # Infer the ICAO address from the message pms.bds.infer(msg) # Infer the Modes-S BDS code - pms.bds.is10(msg) # check if BDS is 1,0 explicitly - pms.bds.is17(msg) # check if BDS is 1,7 explicitly - pms.bds.is20(msg) # check if BDS is 2,0 explicitly - pms.bds.is30(msg) # check if BDS is 3,0 explicitly - pms.bds.is40(msg) # check if BDS is 4,0 explicitly - pms.bds.is44(msg) # check if BDS is 4,4 explicitly - pms.bds.is50(msg) # check if BDS is 5,0 explicitly - pms.bds.is60(msg) # check if BDS is 6,0 explicitly - # check if BDS is 5,0 or 6,0, give reference spd, trk, alt (from ADS-B) pms.bds.is50or60(msg, spd_ref, trk_ref, alt_ref) + # check each BDS explicitly + pms.bds.bds10.is10(msg) + pms.bds.bds17.is17(msg) + pms.bds.bds20.is20(msg) + pms.bds.bds30.is30(msg) + pms.bds.bds40.is40(msg) + pms.bds.bds44.is44(msg) + pms.bds.bds50.is50(msg) + pms.bds.bds60.is60(msg) + + Mode-S elementary surveillance (ELS) ************************************* @@ -206,6 +230,7 @@ Meteorological routine air report (MRAR) [Experimental] pms.commb.p44(msg, rev=False) # pressure (hPa) pms.commb.hum44(msg, rev=False) # humidity (%) + Developement ------------ To perform unit tests. First install ``tox`` through pip, Then, run the following commands: diff --git a/doc/pmslive-screenshot.png b/doc/pmslive-screenshot.png new file mode 100644 index 0000000..843df17 Binary files /dev/null and b/doc/pmslive-screenshot.png differ diff --git a/pyModeS/decoder/acas.py b/pyModeS/decoder/acas.py new file mode 100644 index 0000000..6666146 --- /dev/null +++ b/pyModeS/decoder/acas.py @@ -0,0 +1,21 @@ +# Copyright (C) 2018 Junzi Sun (TU Delft) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Decoding Air-Air Surveillance (ACAS) DF=0/16 +""" + +from __future__ import absolute_import, print_function, division +from pyModeS.decoder import common diff --git a/pyModeS/decoder/adsb.py b/pyModeS/decoder/adsb.py index 0421d65..3230706 100644 --- a/pyModeS/decoder/adsb.py +++ b/pyModeS/decoder/adsb.py @@ -166,53 +166,6 @@ def speed_heading(msg): return spd, trk_or_hdg -def nic(msg): - """Calculate NIC, navigation integrity category - - Args: - msg (string): 28 bytes hexadecimal message string - - Returns: - int: NIC number (from 0 to 11), -1 if not applicable - """ - if typecode(msg) < 9 or typecode(msg) > 18: - raise RuntimeError("%s: Not a airborne position message, expecting 8 22: - raise RuntimeError("%s: Not a surface position message (5 22: - raise RuntimeError("%s: Not a surface position message (5 18: - raise RuntimeError("%s: Not a airborne position message, expecting 8 18: + raise RuntimeError("%s: Not a airborne position message, expecting 8. + +""" +Decoding all call replies DF=11 +""" + +from __future__ import absolute_import, print_function, division +from pyModeS.decoder import common diff --git a/pyModeS/decoder/surv.py b/pyModeS/decoder/surv.py new file mode 100644 index 0000000..edd4984 --- /dev/null +++ b/pyModeS/decoder/surv.py @@ -0,0 +1,21 @@ +# Copyright (C) 2018 Junzi Sun (TU Delft) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Warpper for short roll call surveillance replies DF=4/5 +""" + +from __future__ import absolute_import, print_function, division +from pyModeS.decoder import common diff --git a/pyModeS/extra/beastclient.py b/pyModeS/extra/tcpclient.py similarity index 82% rename from pyModeS/extra/beastclient.py rename to pyModeS/extra/tcpclient.py index 370a631..6510325 100644 --- a/pyModeS/extra/beastclient.py +++ b/pyModeS/extra/tcpclient.py @@ -2,6 +2,7 @@ Stream beast raw data from a TCP server, convert to mode-s messages ''' from __future__ import print_function, division +import os import sys import socket import time @@ -13,12 +14,15 @@ else: PY_VERSION = 2 class BaseClient(Thread): - def __init__(self, host, port): + def __init__(self, host, port, rawtype): Thread.__init__(self) self.host = host self.port = port self.buffer = [] - + self.rawtype = rawtype + if self.rawtype not in ['avr', 'beast']: + print("rawtype must be either avr or beast") + os._exit(1) def connect(self): while True: @@ -33,6 +37,33 @@ class BaseClient(Thread): print("Socket connection error: %s. reconnecting..." % err) time.sleep(3) + + def read_avr_buffer(self): + # -- testing -- + # for b in self.buffer: + # print(chr(b), b) + + # Append message with 0-9,A-F,a-f, until stop sign + + messages = [] + + msg_stop = False + for b in self.buffer: + if b == 59: + msg_stop = True + ts = time.time() + messages.append([self.current_msg, ts]) + if b == 42: + msg_stop = False + self.current_msg = '' + + if (not msg_stop) and (48<=b<=57 or 65<=b<=70 or 97<=b<=102): + self.current_msg = self.current_msg + chr(b) + + self.buffer = [] + + return messages + def read_beast_buffer(self): ''' "1" : 6 byte MLAT timestamp, 1 byte signal level, @@ -91,6 +122,8 @@ class BaseClient(Thread): # extract messages messages = [] for mm in messages_mlat: + ts = time.time() + msgtype = mm[0] # print(''.join('%02X' % i for i in mm)) @@ -108,11 +141,10 @@ class BaseClient(Thread): # incomplete message continue - ts = time.time() - messages.append([msg, ts]) return messages + def handle_messages(self, messages): """re-implement this method to handle the messages""" for msg, t in messages: @@ -136,7 +168,10 @@ class BaseClient(Thread): # continue # -- Removed!! Cause delay in low data rate scenario -- - messages = self.read_beast_buffer() + if self.rawtype == 'beast': + messages = self.read_beast_buffer() + elif self.rawtype == 'avr': + messages = self.read_avr_buffer() if not messages: continue diff --git a/pyModeS/streamer/__init__.py b/pyModeS/streamer/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyModeS/streamer/pmstream.py b/pyModeS/streamer/pmslive old mode 100644 new mode 100755 similarity index 62% rename from pyModeS/streamer/pmstream.py rename to pyModeS/streamer/pmslive index 450d4e9..463a74e --- a/pyModeS/streamer/pmstream.py +++ b/pyModeS/streamer/pmslive @@ -1,102 +1,105 @@ -from __future__ import print_function, division -import os -import sys -import argparse -import curses -import numpy as np -import time -from threading import Lock -import pyModeS as pms -from pyModeS.extra.beastclient import BaseClient -from pyModeS.streamer.stream import Stream -from pyModeS.streamer.screen import Screen - -LOCK = Lock() -ADSB_MSG = [] -ADSB_TS = [] -EHS_MSG = [] -EHS_TS = [] - -parser = argparse.ArgumentParser() -parser.add_argument('--server', help='server address or IP', required=True) -parser.add_argument('--port', help='Raw beast port', required=True) -parser.add_argument('--lat0', help='Latitude of receiver', required=True) -parser.add_argument('--lon0', help='Longitude of receiver', required=True) -args = parser.parse_args() - -SERVER = args.server -PORT = int(args.port) -LAT0 = float(args.lat0) # 51.9899 for TU Delft -LON0 = float(args.lon0) # 4.3754 - -class ModesClient(BaseClient): - def __init__(self, host, port): - super(ModesClient, self).__init__(host, port) - - def handle_messages(self, messages): - local_buffer_adsb_msg = [] - local_buffer_adsb_ts = [] - local_buffer_ehs_msg = [] - local_buffer_ehs_ts = [] - - for msg, t in messages: - if len(msg) < 28: # only process long messages - continue - - df = pms.df(msg) - - if df == 17 or df == 18: - local_buffer_adsb_msg.append(msg) - local_buffer_adsb_ts.append(t) - elif df == 20 or df == 21: - local_buffer_ehs_msg.append(msg) - local_buffer_ehs_ts.append(t) - else: - continue - - - LOCK.acquire() - ADSB_MSG.extend(local_buffer_adsb_msg) - ADSB_TS.extend(local_buffer_adsb_ts) - EHS_MSG.extend(local_buffer_ehs_msg) - EHS_TS.extend(local_buffer_ehs_ts) - LOCK.release() - - -sys.stdout = open(os.devnull, 'w') - -client = ModesClient(host=SERVER, port=PORT) -client.daemon = True -client.start() - -stream = Stream(lat0=LAT0, lon0=LON0) - -try: - screen = Screen() - screen.daemon = True - screen.start() - - while True: - if len(ADSB_MSG) > 200: - LOCK.acquire() - stream.process_raw(ADSB_TS, ADSB_MSG, EHS_TS, EHS_MSG) - ADSB_MSG = [] - ADSB_TS = [] - EHS_MSG = [] - EHS_TS = [] - LOCK.release() - - acs = stream.get_aircraft() - # try: - screen.update_data(acs) - screen.update() - # except KeyboardInterrupt: - # raise - # except: - # continue - -except KeyboardInterrupt: - sys.exit(0) - -finally: - curses.endwin() +#!/usr/bin/env python + +from __future__ import print_function, division +import os +import sys +import argparse +import curses +from threading import Lock +import pyModeS as pms +from pyModeS.extra.tcpclient import BaseClient +from pyModeS.streamer.stream import Stream +from pyModeS.streamer.screen import Screen + +LOCK = Lock() +ADSB_MSG = [] +ADSB_TS = [] +COMMB_MSG = [] +COMMB_TS = [] + +parser = argparse.ArgumentParser() +parser.add_argument('--server', help='server address or IP', required=True) +parser.add_argument('--port', help='raw data port', required=True) +parser.add_argument('--rawtype', help='beast or avr', required=True) +parser.add_argument('--latlon', help='receiver position', nargs=2, metavar=('LAT', 'LON'), required=True) +args = parser.parse_args() + +SERVER = args.server +PORT = int(args.port) +RAWTYPE = args.rawtype +LAT0 = float(args.latlon[0]) +LON0 = float(args.latlon[1]) + + +class ModesClient(BaseClient): + def __init__(self, host, port, rawtype): + super(ModesClient, self).__init__(host, port, rawtype) + + def handle_messages(self, messages): + local_buffer_adsb_msg = [] + local_buffer_adsb_ts = [] + local_buffer_ehs_msg = [] + local_buffer_ehs_ts = [] + + for msg, t in messages: + if len(msg) < 28: # only process long messages + continue + + df = pms.df(msg) + + if df == 17 or df == 18: + local_buffer_adsb_msg.append(msg) + local_buffer_adsb_ts.append(t) + elif df == 20 or df == 21: + local_buffer_ehs_msg.append(msg) + local_buffer_ehs_ts.append(t) + else: + continue + + + LOCK.acquire() + ADSB_MSG.extend(local_buffer_adsb_msg) + ADSB_TS.extend(local_buffer_adsb_ts) + COMMB_MSG.extend(local_buffer_ehs_msg) + COMMB_TS.extend(local_buffer_ehs_ts) + LOCK.release() + + +# redirect all stdout to null, avoiding messing up with the screen +sys.stdout = open(os.devnull, 'w') + +client = ModesClient(host=SERVER, port=PORT, rawtype=RAWTYPE) +client.daemon = True +client.start() + +stream = Stream(lat0=LAT0, lon0=LON0) + +try: + screen = Screen() + screen.daemon = True + screen.start() + + while True: + if len(ADSB_MSG) > 200: + LOCK.acquire() + stream.process_raw(ADSB_TS, ADSB_MSG, COMMB_TS, COMMB_MSG) + ADSB_MSG = [] + ADSB_TS = [] + COMMB_MSG = [] + COMMB_TS = [] + LOCK.release() + + acs = stream.get_aircraft() + try: + screen.update_data(acs) + screen.update() + except KeyboardInterrupt: + raise + except: + continue + +except KeyboardInterrupt: + sys.exit(0) + +finally: + curses.endwin() diff --git a/pyModeS/streamer/screen.py b/pyModeS/streamer/screen.py index cc45e38..1e9494d 100644 --- a/pyModeS/streamer/screen.py +++ b/pyModeS/streamer/screen.py @@ -1,16 +1,35 @@ from __future__ import print_function, division +import os import curses import numpy as np import time from threading import Thread -COLUMNS = ['lat', 'lon', 'alt', 'gs', 'tas', 'ias', 'mach', 'roc', 'trk', 'hdg', 't'] +COLUMNS = [ + ('lat', 10), + ('lon', 10), + ('alt', 7), + ('gs', 5), + ('tas', 5), + ('ias', 5), + ('mach', 7), + ('roc', 7), + ('trk', 10), + ('hdg', 10), + ('ver', 4), + ('NIC', 5), + ('NACv', 5), + ('NACp', 5), + ('SIL', 5), + ('live', 6), +] class Screen(Thread): def __init__(self): Thread.__init__(self) self.screen = curses.initscr() curses.noecho() + curses.mousemask(1) self.screen.keypad(True) self.y = 3 self.x = 1 @@ -27,7 +46,7 @@ class Screen(Thread): def draw_frame(self): self.screen.border(0) - self.screen.addstr(0, 2, "Online aircraft ('crtl+c' to exit, 'enter' to select)") + self.screen.addstr(0, 2, "Online aircraft ('ESC' to exit, 'Enter' to lock one)") def update(self): if len(self.acs) == 0: @@ -44,14 +63,17 @@ class Screen(Thread): row = 1 - header = 'icao' - for c in COLUMNS: - c = 'updated' if c=='t' else c - header += '%10s' % c + header = ' icao' + for c, cw in COLUMNS: + header += (cw-len(c))*' ' + c + + # fill end with spaces + header += (self.scr_w - 2 - len(header)) * ' ' if len(header) > self.scr_w - 2: header = header[:self.scr_w-3] + '>' + self.screen.addstr(row, 1, header) row +=1 @@ -74,19 +96,23 @@ class Screen(Thread): line += icao - for c in COLUMNS: - - if c == 't': - val = str(int(ac[c])) - line += '%12s' % val + for c, cw in COLUMNS: + if c=='live': + val = int(time.time() - ac[c]) + elif ac[c] is None: + val = '' else: - val = '' if ac[c] is None else ac[c] - line += '%10s' % val + val = ac[c] + val_str = str(val) + line += (cw-len(val_str))*' ' + val_str + + # fill end with spaces + line += (self.scr_w - 2 - len(line)) * ' ' if len(line) > self.scr_w - 2: line = line[:self.scr_w-3] + '>' - if self.lock_icao == icao: + if (icao is not None) and (self.lock_icao == icao): self.screen.addstr(row, 1, line, curses.A_STANDOUT) elif row == self.y: self.screen.addstr(row, 1, line, curses.A_BOLD) @@ -108,7 +134,10 @@ class Screen(Thread): while True: c = self.screen.getch() - if c == curses.KEY_HOME: + if c == 27: + curses.endwin() + os._exit(1) + elif c == curses.KEY_HOME: self.x = 1 self.y = 1 elif c == curses.KEY_NPAGE: @@ -131,3 +160,6 @@ class Screen(Thread): self.y = y_intent elif c == curses.KEY_ENTER or c == 10 or c == 13: self.lock_icao = (self.screen.instr(self.y, 1, 6)).decode() + elif c == curses.KEY_F5: + self.screen.refresh() + self.draw_frame() diff --git a/pyModeS/streamer/stream.py b/pyModeS/streamer/stream.py index 0c618e6..497e066 100644 --- a/pyModeS/streamer/stream.py +++ b/pyModeS/streamer/stream.py @@ -1,7 +1,7 @@ from __future__ import absolute_import, print_function, division import numpy as np import time -from pyModeS.decoder import adsb, ehs +import pyModeS as pms class Stream(): def __init__(self, lat0, lon0): @@ -18,8 +18,8 @@ class Stream(): self.cache_timeout = 60 # seconds - def process_raw(self, adsb_ts, adsb_msgs, ehs_ts, ehs_msgs, tnow=None): - """process a chunk of adsb and ehs messages recieved in the same + 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. """ if tnow is None: @@ -31,11 +31,12 @@ class Stream(): # process adsb message for t, msg in zip(adsb_ts, adsb_msgs): - icao = adsb.icao(msg) - tc = adsb.typecode(msg) + icao = pms.icao(msg) + tc = pms.adsb.typecode(msg) if icao not in self.acs: self.acs[icao] = { + 'live': None, 'lat': None, 'lon': None, 'alt': None, @@ -46,20 +47,20 @@ class Stream(): 'ias': None, 'mach': None, 'hdg': None, - 'adsb_version' : None, - 'nic_s' : None, - 'nic_a' : None, - 'nic_b' : None, - 'nic_c' : None + 'ver' : None, + 'NIC' : None, + 'NACp' : None, + 'NACv' : None, + 'SIL' : None } - self.acs[icao]['t'] = t + self.acs[icao]['live'] = int(t) if 1 <= tc <= 4: - self.acs[icao]['callsign'] = adsb.callsign(msg) + self.acs[icao]['callsign'] = pms.adsb.callsign(msg) if (5 <= tc <= 8) or (tc == 19): - vdata = adsb.velocity(msg) + vdata = pms.adsb.velocity(msg) if vdata is None: continue @@ -75,7 +76,7 @@ class Stream(): self.acs[icao]['tv'] = t if (5 <= tc <= 18): - oe = adsb.oe_flag(msg) + oe = pms.adsb.oe_flag(msg) self.acs[icao][oe] = msg self.acs[icao]['t'+str(oe)] = t @@ -83,21 +84,21 @@ class Stream(): # use single message decoding rlat = self.acs[icao]['lat'] rlon = self.acs[icao]['lon'] - latlon = adsb.position_with_ref(msg, rlat, rlon) + latlon = pms.adsb.position_with_ref(msg, rlat, rlon) elif ('t0' in self.acs[icao]) and ('t1' in self.acs[icao]) and \ (abs(self.acs[icao]['t0'] - self.acs[icao]['t1']) < 10): # use multi message decoding - try: - latlon = adsb.position( - self.acs[icao][0], - self.acs[icao][1], - self.acs[icao]['t0'], - self.acs[icao]['t1'], - self.lat0, self.lon0 - ) - except: - # mix of surface and airborne position message - continue + # try: + latlon = pms.adsb.position( + self.acs[icao][0], + self.acs[icao][1], + self.acs[icao]['t0'], + self.acs[icao]['t1'], + self.lat0, self.lon0 + ) + # except: + # # mix of surface and airborne position message + # continue else: latlon = None @@ -105,71 +106,60 @@ class Stream(): self.acs[icao]['tpos'] = t self.acs[icao]['lat'] = latlon[0] self.acs[icao]['lon'] = latlon[1] +<<<<<<< HEAD self.acs[icao]['alt'] = adsb.altitude(msg) # local_updated_acs_buffer.append(icao)acs[icao]['adsb_version'] local_updated_acs_buffer.append(acs[icao]['adsb_version']) +======= + self.acs[icao]['alt'] = pms.adsb.altitude(msg) + local_updated_acs_buffer.append(icao) +>>>>>>> upstream/master # Uncertainty & accuracy - if (5 <= tc <= 8): - if self.acs[icao]['adsb_version'] == 1: - if self.acs[icao]['nic_s'] != None: - self.nic = adsb.nic_v1(msg,self.acs[icao]['nic_s']) - elif self.acs[icao]['adsb_version'] == 2: - if self.acs[icao]['nic_a'] != None and self.acs[icao]['nic_b'] != None: - self.nic = adsb.nic_v2(msg,self.nic_a,self.acs[icao]['nic_b'],self.acs[icao]['nic_c']) - if (9 <= tc <= 18): - if self.acs[icao]['adsb_version'] == 1: - if self.acs[icao]['nic_s'] != None: - self.nic = adsb.nic_v1(msg,self.acs[icao]['nic_s']) - elif self.acs[icao]['adsb_version'] == 2: - self.acs[icao]['nic_b'] = adsb.nic_b(msg) - if self.acs[icao]['nic_a'] != None and self.acs[icao]['nic_b'] != None: - self.nic = adsb.nic_v2(msg,self.acs[icao]['nic_a'],self.nic_b,self.acs[icao]['nic_c']) + ac = self.acs[icao] + + if (5 <= tc <= 8) or (9 <= tc <= 18) or (20 <= tc <= 22): + if (ac['ver'] == 1) and ('nic_s' in ac.keys()): + self.acs[icao]['NIC'] = pms.adsb.nic_v1(msg, ac['nic_s']) + elif (ac['ver'] == 2) and ('nic_a' in ac.keys()) and ('nic_b' in ac.keys()): + self.acs[icao]['NIC'] = pms.adsb.nic_v2(msg, ac['nic_a'], ac['nic_b'], ac['nic_c']) if tc == 19: - self.acs[icao]['nac_v'] = adsb.nac_v(msg) - if (20 <= tc <= 22): - if self.acs[icao]['adsb_version'] == 1: - if self.acs[icao]['nic_s'] != None: - self.nic = adsb.nic_v1(msg,self.acs[icao]['nic_s']) - elif self.acs[icao]['adsb_version'] == 2: - if self.acs[icao]['nic_a'] != None and self.acs[icao]['nic_b'] != None: - self.nic = adsb.nic_v2(msg,self.acs[icao]['nic_a'],self.acs[icao]['nic_b'],self.acs[icao]['nic_c']) + if ac['ver'] in [1, 2]: + self.acs[icao]['NACv'] = pms.adsb.nac_v(msg) if tc == 29: - if self.acs[icao]['adsb_version'] != None: - self.acs[icao]['sil'] = adsb.sil(msg,self.acs[icao]['adsb_version']) - self.acs[icao]['nac_p'] = adsb.nac_p(msg) + if ac['ver'] != None: + self.acs[icao]['SIL'], self.acs[icao]['sil_s'] = pms.adsb.sil(msg, ac['ver']) + self.acs[icao]['NACp'] = pms.adsb.nac_p(msg) if tc == 31: - self.acs[icao]['adsb_version'] = adsb.version(msg) - self.acs[icao]['sil'] = adsb.version(msg) - self.acs[icao]['nac_p'] = adsb.nac_p(msg) - if self.acs[icao]['adsb_version'] == 1: - self.acs[icao]['nic_s'] = adsb.nic_s(msg) - elif self.acs[icao]['adsb_version'] == 2: - self.acs[icao]['nic_a'] , self.acs[icao]['nic_c'] = adsb.nic_a_and_c(msg) + self.acs[icao]['ver'] = pms.adsb.version(msg) + self.acs[icao]['SIL'] = pms.adsb.version(msg) + self.acs[icao]['NACp'] = pms.adsb.nac_p(msg) + if self.acs[icao]['ver'] == 1: + self.acs[icao]['nic_s'] = pms.adsb.nic_s(msg) + elif self.acs[icao]['ver'] == 2: + self.acs[icao]['nic_a'], self.acs[icao]['nic_c'] = pms.adsb.nic_a_c(msg) - - - # process ehs message - for t, msg in zip(ehs_ts, ehs_msgs): - icao = ehs.icao(msg) + # process commb message + for t, msg in zip(commb_ts, commb_msgs): + icao = pms.icao(msg) if icao not in self.acs: continue - bds = ehs.BDS(msg) + bds = pms.bds.infer(msg) if bds == 'BDS50': - tas = ehs.tas50(msg) + tas = pms.commb.tas50(msg) if tas: self.acs[icao]['t50'] = t self.acs[icao]['tas'] = tas elif bds == 'BDS60': - ias = ehs.ias60(msg) - hdg = ehs.hdg60(msg) - mach = ehs.mach60(msg) + ias = pms.commb.ias60(msg) + hdg = pms.commb.hdg60(msg) + mach = pms.commb.mach60(msg) if ias or hdg or mach: self.acs[icao]['t60'] = t @@ -182,7 +172,7 @@ class Stream(): # clear up old data for icao in list(self.acs.keys()): - if self.t - self.acs[icao]['t'] > self.cache_timeout: + if self.t - self.acs[icao]['live'] > self.cache_timeout: del self.acs[icao] continue @@ -214,4 +204,4 @@ class Stream(): def reset_new_aircraft(self): """reset the updated icao buffer once been read""" - self.__new_acs = set() \ No newline at end of file + self.__new_acs = set() diff --git a/setup.py b/setup.py index af6289c..6a53144 100644 --- a/setup.py +++ b/setup.py @@ -117,4 +117,6 @@ setup( # 'sample=sample:main', # ], # }, + + scripts=['pyModeS/streamer/pmslive'], )