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'],
)