"fetch from upstream"
This commit is contained in:
commit
6db5ea8023
47
README.rst
47
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:
|
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=1-4 / BDS 0,8: Aircraft identification and category
|
||||||
- TC=5-8 / BDS 0,6: Surface position
|
- TC=5-8 / BDS 0,6: Surface position
|
||||||
@ -40,7 +40,7 @@ New features in v2.0
|
|||||||
---------------------
|
---------------------
|
||||||
- New structure of the libraries
|
- New structure of the libraries
|
||||||
- ADS-B and Comm-B data streaming
|
- ADS-B and Comm-B data streaming
|
||||||
- Active aircraft viewing (terminal cursor)
|
- Active aircraft viewing (terminal curses)
|
||||||
- Improved BDS identification
|
- Improved BDS identification
|
||||||
- Optimizing decoding speed
|
- 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
|
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
|
Use the library
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
@ -147,18 +169,20 @@ Common Mode-S functions
|
|||||||
pms.icao(msg) # Infer the ICAO address from the message
|
pms.icao(msg) # Infer the ICAO address from the message
|
||||||
pms.bds.infer(msg) # Infer the Modes-S BDS code
|
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)
|
# 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)
|
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)
|
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.p44(msg, rev=False) # pressure (hPa)
|
||||||
pms.commb.hum44(msg, rev=False) # humidity (%)
|
pms.commb.hum44(msg, rev=False) # humidity (%)
|
||||||
|
|
||||||
|
|
||||||
Developement
|
Developement
|
||||||
------------
|
------------
|
||||||
To perform unit tests. First install ``tox`` through pip, Then, run the following commands:
|
To perform unit tests. First install ``tox`` through pip, Then, run the following commands:
|
||||||
|
BIN
doc/pmslive-screenshot.png
Normal file
BIN
doc/pmslive-screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
21
pyModeS/decoder/acas.py
Normal file
21
pyModeS/decoder/acas.py
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Decoding Air-Air Surveillance (ACAS) DF=0/16
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import, print_function, division
|
||||||
|
from pyModeS.decoder import common
|
@ -166,53 +166,6 @@ def speed_heading(msg):
|
|||||||
return spd, trk_or_hdg
|
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<TC<19" % msg)
|
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
|
||||||
tc = typecode(msg)
|
|
||||||
nic_sup_b = common.bin2int(msgbin[39])
|
|
||||||
|
|
||||||
if tc in [0, 18, 22]:
|
|
||||||
nic = 0
|
|
||||||
elif tc == 17:
|
|
||||||
nic = 1
|
|
||||||
elif tc == 16:
|
|
||||||
if nic_sup_b:
|
|
||||||
nic = 3
|
|
||||||
else:
|
|
||||||
nic = 2
|
|
||||||
elif tc == 15:
|
|
||||||
nic = 4
|
|
||||||
elif tc == 14:
|
|
||||||
nic = 5
|
|
||||||
elif tc == 13:
|
|
||||||
nic = 6
|
|
||||||
elif tc == 12:
|
|
||||||
nic = 7
|
|
||||||
elif tc == 11:
|
|
||||||
if nic_sup_b:
|
|
||||||
nic = 9
|
|
||||||
else:
|
|
||||||
nic = 8
|
|
||||||
elif tc in [10, 21]:
|
|
||||||
nic = 10
|
|
||||||
elif tc in [9, 20]:
|
|
||||||
nic = 11
|
|
||||||
else:
|
|
||||||
nic = -1
|
|
||||||
return nic
|
|
||||||
|
|
||||||
|
|
||||||
def oe_flag(msg):
|
def oe_flag(msg):
|
||||||
"""Check the odd/even flag. Bit 54, 0 for even, 1 for odd.
|
"""Check the odd/even flag. Bit 54, 0 for even, 1 for odd.
|
||||||
Args:
|
Args:
|
||||||
@ -223,22 +176,47 @@ def oe_flag(msg):
|
|||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
return int(msgbin[53])
|
return int(msgbin[53])
|
||||||
|
|
||||||
# Uncertainty & accuracy
|
|
||||||
|
|
||||||
def nic_v1(msg,nic_sup_b):
|
def version(msg):
|
||||||
"""Calculate NIC, navigation integrity category
|
"""ADS-B Version
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
msg (string): 28 bytes hexadecimal message string, nic_sup_b (int): NIC supplement
|
msg (string): 28 bytes hexadecimal message string, TC = 31
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: version number
|
||||||
|
"""
|
||||||
|
tc = typecode(msg)
|
||||||
|
|
||||||
|
if tc != 31:
|
||||||
|
raise RuntimeError("%s: Not a status operation message, expecting TC = 31" % msg)
|
||||||
|
|
||||||
|
msgbin = common.hex2bin(msg)
|
||||||
|
version = common.bin2int(msgbin[72:75])
|
||||||
|
|
||||||
|
return version
|
||||||
|
|
||||||
|
|
||||||
|
def nic_v1(msg, nic_sup_b):
|
||||||
|
"""Calculate NIC, navigation integrity category for ADS-B version 1
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (string): 28 bytes hexadecimal message string
|
||||||
|
nic_sup_b (int or string): NIC supplement
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
int: NIC number (from 0 to 11), -1 if not applicable
|
int: NIC number (from 0 to 11), -1 if not applicable
|
||||||
"""
|
"""
|
||||||
if typecode(msg) < 5 or typecode(msg) > 22:
|
if typecode(msg) < 5 or typecode(msg) > 22:
|
||||||
raise RuntimeError("%s: Not a surface position message (5<TC<8, )airborne position message (8<TC<19), airborne position with GNSS height (20<TC<22)" % msg)
|
raise RuntimeError("%s: Not a surface position message (5<TC<8), \
|
||||||
|
airborne position message (8<TC<19), \
|
||||||
|
or airborne position with GNSS height (20<TC<22)" % msg)
|
||||||
|
|
||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
|
if nic_sup_b in ['0', '1']:
|
||||||
|
nic_sup_b = int(nic_sup_b)
|
||||||
|
|
||||||
if tc in [0, 8, 18, 22]:
|
if tc in [0, 8, 18, 22]:
|
||||||
nic = 0
|
nic = 0
|
||||||
elif tc == 17:
|
elif tc == 17:
|
||||||
@ -277,19 +255,34 @@ def nic_v1(msg,nic_sup_b):
|
|||||||
nic = -1
|
nic = -1
|
||||||
return nic
|
return nic
|
||||||
|
|
||||||
def nic_v2(msg,nic_a,nic_b,nic_c):
|
|
||||||
"""Calculate NIC, navigation integrity category
|
def nic_v2(msg, nic_a, nic_b, nic_c):
|
||||||
|
"""Calculate NIC, navigation integrity category, for ADS-B version 2
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
msg (string): 28 bytes hexadecimal message string, nic_a (int): NIC supplement, nic_b (int): NIC supplement, nic_c (int): NIC supplement
|
msg (string): 28 bytes hexadecimal message string
|
||||||
|
nic_a (int or string): NIC supplement
|
||||||
|
nic_b (int or srting): NIC supplement
|
||||||
|
nic_c (int or string): NIC supplement
|
||||||
Returns:
|
Returns:
|
||||||
int: NIC number (from 0 to 11), -1 if not applicable
|
int: NIC number (from 0 to 11), -1 if not applicable
|
||||||
"""
|
"""
|
||||||
if typecode(msg) < 5 or typecode(msg) > 22:
|
if typecode(msg) < 5 or typecode(msg) > 22:
|
||||||
raise RuntimeError("%s: Not a surface position message (5<TC<8, )airborne position message (8<TC<19), airborne position with GNSS height (20<TC<22)" % msg)
|
raise RuntimeError("%s: Not a surface position message (5<TC<8) \
|
||||||
|
airborne position message (8<TC<19), \
|
||||||
|
or airborne position with GNSS height (20<TC<22)" % msg)
|
||||||
|
|
||||||
tc = typecode(msg)
|
tc = typecode(msg)
|
||||||
|
|
||||||
|
if nic_a in ['0', '1']:
|
||||||
|
nic_a = int(nic_a)
|
||||||
|
|
||||||
|
if nic_b in ['0', '1']:
|
||||||
|
nic_b = int(nic_b)
|
||||||
|
|
||||||
|
if nic_c in ['0', '1']:
|
||||||
|
nic_c = int(nic_c)
|
||||||
|
|
||||||
if tc in [0, 18, 22]:
|
if tc in [0, 18, 22]:
|
||||||
nic = 0
|
nic = 0
|
||||||
elif tc == 17:
|
elif tc == 17:
|
||||||
@ -343,59 +336,67 @@ def nic_v2(msg,nic_a,nic_b,nic_c):
|
|||||||
return nic
|
return nic
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def nic_s(msg):
|
def nic_s(msg):
|
||||||
"""Calculate NICs, navigation integrity category supplement
|
"""Obtain NIC supplement bit, TC=31 message
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
msg (string): 28 bytes hexadecimal message string
|
msg (string): 28 bytes hexadecimal message string
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
int: NIC number (from 0 to 11), -1 if not applicable
|
int: NICs number (0 or 1)
|
||||||
"""
|
"""
|
||||||
if typecode(msg) != 31:
|
tc = typecode(msg)
|
||||||
|
|
||||||
|
if tc != 31:
|
||||||
raise RuntimeError("%s: Not a status operation message, expecting TC = 31" % msg)
|
raise RuntimeError("%s: Not a status operation message, expecting TC = 31" % msg)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
nic_s = common.bin2int(msgbin[75])
|
nic_s = int(msgbin[75])
|
||||||
|
|
||||||
return nic_s
|
return nic_s
|
||||||
|
|
||||||
def nic_a_and_c(msg):
|
|
||||||
"""Calculate NICa and NICc, navigation integrity category supplements
|
def nic_a_c(msg):
|
||||||
|
"""Obtain NICa/c, navigation integrity category supplements a and c
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
msg (string): 28 bytes hexadecimal message string
|
msg (string): 28 bytes hexadecimal message string
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
int: NIC number (from 0 to 11), -1 if not applicable
|
(int, int): NICa and NICc number (0 or 1)
|
||||||
"""
|
"""
|
||||||
if typecode(msg) != 31:
|
tc = typecode(msg)
|
||||||
|
|
||||||
|
if tc != 31:
|
||||||
raise RuntimeError("%s: Not a status operation message, expecting TC = 31" % msg)
|
raise RuntimeError("%s: Not a status operation message, expecting TC = 31" % msg)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
nic_a = common.bin2int(msgbin[75])
|
nic_a = int(msgbin[75])
|
||||||
nic_c = common.bin2int(msgbin[51])
|
nic_c = int(msgbin[51])
|
||||||
|
|
||||||
return nic_a, nic_c
|
return nic_a, nic_c
|
||||||
|
|
||||||
|
|
||||||
def nic_b(msg):
|
def nic_b(msg):
|
||||||
"""Calculate NICb, navigation integrity category supplement
|
"""Obtain NICb, navigation integrity category supplement-b
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
msg (string): 28 bytes hexadecimal message string
|
msg (string): 28 bytes hexadecimal message string
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
int: NIC number (from 0 to 11), -1 if not applicable
|
int: NICb number (0 or 1)
|
||||||
"""
|
"""
|
||||||
if typecode(msg) < 9 or typecode(msg) > 18:
|
tc = typecode(msg)
|
||||||
raise RuntimeError("%s: Not a airborne position message, expecting 8<TC<19" % msg)
|
|
||||||
|
if tc < 9 or tc > 18:
|
||||||
|
raise RuntimeError("%s: Not a airborne position message, expecting 8<TC<19" % msg)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
nic_b = common.bin2int(msgbin[39])
|
nic_b = int(msgbin[39])
|
||||||
|
|
||||||
return nic_b
|
return nic_b
|
||||||
|
|
||||||
|
|
||||||
def nac_p(msg):
|
def nac_p(msg):
|
||||||
"""Calculate NACp, Navigation Accuracy Category - Position
|
"""Calculate NACp, Navigation Accuracy Category - Position
|
||||||
|
|
||||||
@ -403,19 +404,21 @@ def nac_p(msg):
|
|||||||
msg (string): 28 bytes hexadecimal message string, TC = 29 or 31
|
msg (string): 28 bytes hexadecimal message string, TC = 29 or 31
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
int: NACp number (from 0 to 11), -1 if not applicable
|
int: NACp number (0 or 1)
|
||||||
"""
|
"""
|
||||||
if typecode(msg) not in [29,31]:
|
tc = typecode(msg)
|
||||||
raise RuntimeError("%s: Not a target state and status message neither operation status message, expecting TC = 29 or 31" % msg)
|
|
||||||
|
if tc not in [29, 31]:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, \
|
||||||
|
or operation status message, expecting TC = 29 or 31" % msg)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
tc = typecode(msg)
|
|
||||||
if tc == 29:
|
if tc == 29:
|
||||||
nac_p = common.bin2int(msgbin[71:75])
|
nac_p = common.bin2int(msgbin[71:75])
|
||||||
elif tc == 31:
|
elif tc == 31:
|
||||||
nac_p = common.bin2int(msgbin[76:80])
|
nac_p = common.bin2int(msgbin[76:80])
|
||||||
else:
|
|
||||||
nac_p = -1
|
|
||||||
return nac_p
|
return nac_p
|
||||||
|
|
||||||
|
|
||||||
@ -428,63 +431,44 @@ def nac_v(msg):
|
|||||||
Returns:
|
Returns:
|
||||||
int: NACv number (from 0 to 4), -1 if not applicable
|
int: NACv number (from 0 to 4), -1 if not applicable
|
||||||
"""
|
"""
|
||||||
if typecode(msg) != 19:
|
tc = typecode(msg)
|
||||||
|
|
||||||
|
if tc != 19:
|
||||||
raise RuntimeError("%s: Not an airborne velocity message, expecting TC = 19" % msg)
|
raise RuntimeError("%s: Not an airborne velocity message, expecting TC = 19" % msg)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
tc = typecode(msg)
|
nac_v = common.bin2int(msgbin[42:45])
|
||||||
if tc == 19:
|
|
||||||
nac_v = common.bin2int(msgbin[42:45])
|
|
||||||
else:
|
|
||||||
nac_v = -1
|
|
||||||
return nac_v
|
return nac_v
|
||||||
|
|
||||||
def sil(msg,version):
|
|
||||||
"""Calculate SIL, Surveillance Integrity Level
|
def sil(msg, version):
|
||||||
|
"""Calculate SIL, Surveillance Integrity Level
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
msg (string): 28 bytes hexadecimal message string with TC = 29, 31
|
msg (string): 28 bytes hexadecimal message string with TC = 29, 31
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
int: sil number, -1 if not applicable
|
(int, int): sil number and sil supplement (only for v2)
|
||||||
"""
|
"""
|
||||||
if typecode(msg) not in [29,31]:
|
tc = typecode(msg)
|
||||||
raise RuntimeError("%s: Not a target state and status message neither operation status message, expecting TC = 29 or 31" % msg)
|
|
||||||
|
if tc not in [29, 31]:
|
||||||
|
raise RuntimeError("%s: Not a target state and status messag, \
|
||||||
|
or operation status message, expecting TC = 29 or 31" % msg)
|
||||||
|
|
||||||
msgbin = common.hex2bin(msg)
|
msgbin = common.hex2bin(msg)
|
||||||
tc = typecode(msg)
|
|
||||||
if tc == 29:
|
if tc == 29:
|
||||||
sil = common.bin2int(msgbin[76:78])
|
sil = common.bin2int(msgbin[76:78])
|
||||||
elif tc == 31:
|
elif tc == 31:
|
||||||
sil = common.bin2int(msg[82:84])
|
sil = common.bin2int(msg[82:84])
|
||||||
else:
|
|
||||||
sil = -1
|
sil_sup = None
|
||||||
|
|
||||||
if version == 2:
|
if version == 2:
|
||||||
if typecode(msg) == 29:
|
if version == 29:
|
||||||
sils = common.bin2int(msgbin[39])
|
sil_sup = common.bin2int(msgbin[39])
|
||||||
elif typecode(msg) == 31:
|
elif version == 31:
|
||||||
sils = common.bin2int(msgbin[86])
|
sil_sup = common.bin2int(msgbin[86])
|
||||||
else:
|
|
||||||
sils = -1
|
|
||||||
|
|
||||||
return sil, sils
|
return sil, sil_sup
|
||||||
|
|
||||||
def version(msg):
|
|
||||||
"""ADS-B Version
|
|
||||||
|
|
||||||
Args:
|
|
||||||
msg (string): 28 bytes hexadecimal message string, TC = 31
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
int: version number
|
|
||||||
"""
|
|
||||||
msgbin = common.hex2bin(msg)
|
|
||||||
if typecode(msg) not in [29,31]:
|
|
||||||
raise RuntimeError("%s: Not a target state and status message neither operation status message, expecting TC = 29 or 31" % msg)
|
|
||||||
|
|
||||||
if typecode(msg) in [29,31]:
|
|
||||||
version = common.bin2int(msgbin[72:75])
|
|
||||||
else:
|
|
||||||
version = -1
|
|
||||||
return version
|
|
||||||
|
21
pyModeS/decoder/allcall.py
Normal file
21
pyModeS/decoder/allcall.py
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Decoding all call replies DF=11
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import, print_function, division
|
||||||
|
from pyModeS.decoder import common
|
21
pyModeS/decoder/surv.py
Normal file
21
pyModeS/decoder/surv.py
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Warpper for short roll call surveillance replies DF=4/5
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import, print_function, division
|
||||||
|
from pyModeS.decoder import common
|
@ -2,6 +2,7 @@
|
|||||||
Stream beast raw data from a TCP server, convert to mode-s messages
|
Stream beast raw data from a TCP server, convert to mode-s messages
|
||||||
'''
|
'''
|
||||||
from __future__ import print_function, division
|
from __future__ import print_function, division
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
@ -13,12 +14,15 @@ else:
|
|||||||
PY_VERSION = 2
|
PY_VERSION = 2
|
||||||
|
|
||||||
class BaseClient(Thread):
|
class BaseClient(Thread):
|
||||||
def __init__(self, host, port):
|
def __init__(self, host, port, rawtype):
|
||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
self.buffer = []
|
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):
|
def connect(self):
|
||||||
while True:
|
while True:
|
||||||
@ -33,6 +37,33 @@ class BaseClient(Thread):
|
|||||||
print("Socket connection error: %s. reconnecting..." % err)
|
print("Socket connection error: %s. reconnecting..." % err)
|
||||||
time.sleep(3)
|
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):
|
def read_beast_buffer(self):
|
||||||
'''
|
'''
|
||||||
<esc> "1" : 6 byte MLAT timestamp, 1 byte signal level,
|
<esc> "1" : 6 byte MLAT timestamp, 1 byte signal level,
|
||||||
@ -91,6 +122,8 @@ class BaseClient(Thread):
|
|||||||
# extract messages
|
# extract messages
|
||||||
messages = []
|
messages = []
|
||||||
for mm in messages_mlat:
|
for mm in messages_mlat:
|
||||||
|
ts = time.time()
|
||||||
|
|
||||||
msgtype = mm[0]
|
msgtype = mm[0]
|
||||||
# print(''.join('%02X' % i for i in mm))
|
# print(''.join('%02X' % i for i in mm))
|
||||||
|
|
||||||
@ -108,11 +141,10 @@ class BaseClient(Thread):
|
|||||||
# incomplete message
|
# incomplete message
|
||||||
continue
|
continue
|
||||||
|
|
||||||
ts = time.time()
|
|
||||||
|
|
||||||
messages.append([msg, ts])
|
messages.append([msg, ts])
|
||||||
return messages
|
return messages
|
||||||
|
|
||||||
|
|
||||||
def handle_messages(self, messages):
|
def handle_messages(self, messages):
|
||||||
"""re-implement this method to handle the messages"""
|
"""re-implement this method to handle the messages"""
|
||||||
for msg, t in messages:
|
for msg, t in messages:
|
||||||
@ -136,7 +168,10 @@ class BaseClient(Thread):
|
|||||||
# continue
|
# continue
|
||||||
# -- Removed!! Cause delay in low data rate scenario --
|
# -- 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:
|
if not messages:
|
||||||
continue
|
continue
|
0
pyModeS/streamer/__init__.py
Normal file
0
pyModeS/streamer/__init__.py
Normal file
207
pyModeS/streamer/pmstream.py → pyModeS/streamer/pmslive
Normal file → Executable file
207
pyModeS/streamer/pmstream.py → pyModeS/streamer/pmslive
Normal file → Executable file
@ -1,102 +1,105 @@
|
|||||||
from __future__ import print_function, division
|
#!/usr/bin/env python
|
||||||
import os
|
|
||||||
import sys
|
from __future__ import print_function, division
|
||||||
import argparse
|
import os
|
||||||
import curses
|
import sys
|
||||||
import numpy as np
|
import argparse
|
||||||
import time
|
import curses
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
import pyModeS as pms
|
import pyModeS as pms
|
||||||
from pyModeS.extra.beastclient import BaseClient
|
from pyModeS.extra.tcpclient import BaseClient
|
||||||
from pyModeS.streamer.stream import Stream
|
from pyModeS.streamer.stream import Stream
|
||||||
from pyModeS.streamer.screen import Screen
|
from pyModeS.streamer.screen import Screen
|
||||||
|
|
||||||
LOCK = Lock()
|
LOCK = Lock()
|
||||||
ADSB_MSG = []
|
ADSB_MSG = []
|
||||||
ADSB_TS = []
|
ADSB_TS = []
|
||||||
EHS_MSG = []
|
COMMB_MSG = []
|
||||||
EHS_TS = []
|
COMMB_TS = []
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('--server', help='server address or IP', required=True)
|
parser.add_argument('--server', help='server address or IP', required=True)
|
||||||
parser.add_argument('--port', help='Raw beast port', required=True)
|
parser.add_argument('--port', help='raw data port', required=True)
|
||||||
parser.add_argument('--lat0', help='Latitude of receiver', required=True)
|
parser.add_argument('--rawtype', help='beast or avr', required=True)
|
||||||
parser.add_argument('--lon0', help='Longitude of receiver', required=True)
|
parser.add_argument('--latlon', help='receiver position', nargs=2, metavar=('LAT', 'LON'), required=True)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
SERVER = args.server
|
SERVER = args.server
|
||||||
PORT = int(args.port)
|
PORT = int(args.port)
|
||||||
LAT0 = float(args.lat0) # 51.9899 for TU Delft
|
RAWTYPE = args.rawtype
|
||||||
LON0 = float(args.lon0) # 4.3754
|
LAT0 = float(args.latlon[0])
|
||||||
|
LON0 = float(args.latlon[1])
|
||||||
class ModesClient(BaseClient):
|
|
||||||
def __init__(self, host, port):
|
|
||||||
super(ModesClient, self).__init__(host, port)
|
class ModesClient(BaseClient):
|
||||||
|
def __init__(self, host, port, rawtype):
|
||||||
def handle_messages(self, messages):
|
super(ModesClient, self).__init__(host, port, rawtype)
|
||||||
local_buffer_adsb_msg = []
|
|
||||||
local_buffer_adsb_ts = []
|
def handle_messages(self, messages):
|
||||||
local_buffer_ehs_msg = []
|
local_buffer_adsb_msg = []
|
||||||
local_buffer_ehs_ts = []
|
local_buffer_adsb_ts = []
|
||||||
|
local_buffer_ehs_msg = []
|
||||||
for msg, t in messages:
|
local_buffer_ehs_ts = []
|
||||||
if len(msg) < 28: # only process long messages
|
|
||||||
continue
|
for msg, t in messages:
|
||||||
|
if len(msg) < 28: # only process long messages
|
||||||
df = pms.df(msg)
|
continue
|
||||||
|
|
||||||
if df == 17 or df == 18:
|
df = pms.df(msg)
|
||||||
local_buffer_adsb_msg.append(msg)
|
|
||||||
local_buffer_adsb_ts.append(t)
|
if df == 17 or df == 18:
|
||||||
elif df == 20 or df == 21:
|
local_buffer_adsb_msg.append(msg)
|
||||||
local_buffer_ehs_msg.append(msg)
|
local_buffer_adsb_ts.append(t)
|
||||||
local_buffer_ehs_ts.append(t)
|
elif df == 20 or df == 21:
|
||||||
else:
|
local_buffer_ehs_msg.append(msg)
|
||||||
continue
|
local_buffer_ehs_ts.append(t)
|
||||||
|
else:
|
||||||
|
continue
|
||||||
LOCK.acquire()
|
|
||||||
ADSB_MSG.extend(local_buffer_adsb_msg)
|
|
||||||
ADSB_TS.extend(local_buffer_adsb_ts)
|
LOCK.acquire()
|
||||||
EHS_MSG.extend(local_buffer_ehs_msg)
|
ADSB_MSG.extend(local_buffer_adsb_msg)
|
||||||
EHS_TS.extend(local_buffer_ehs_ts)
|
ADSB_TS.extend(local_buffer_adsb_ts)
|
||||||
LOCK.release()
|
COMMB_MSG.extend(local_buffer_ehs_msg)
|
||||||
|
COMMB_TS.extend(local_buffer_ehs_ts)
|
||||||
|
LOCK.release()
|
||||||
sys.stdout = open(os.devnull, 'w')
|
|
||||||
|
|
||||||
client = ModesClient(host=SERVER, port=PORT)
|
# redirect all stdout to null, avoiding messing up with the screen
|
||||||
client.daemon = True
|
sys.stdout = open(os.devnull, 'w')
|
||||||
client.start()
|
|
||||||
|
client = ModesClient(host=SERVER, port=PORT, rawtype=RAWTYPE)
|
||||||
stream = Stream(lat0=LAT0, lon0=LON0)
|
client.daemon = True
|
||||||
|
client.start()
|
||||||
try:
|
|
||||||
screen = Screen()
|
stream = Stream(lat0=LAT0, lon0=LON0)
|
||||||
screen.daemon = True
|
|
||||||
screen.start()
|
try:
|
||||||
|
screen = Screen()
|
||||||
while True:
|
screen.daemon = True
|
||||||
if len(ADSB_MSG) > 200:
|
screen.start()
|
||||||
LOCK.acquire()
|
|
||||||
stream.process_raw(ADSB_TS, ADSB_MSG, EHS_TS, EHS_MSG)
|
while True:
|
||||||
ADSB_MSG = []
|
if len(ADSB_MSG) > 200:
|
||||||
ADSB_TS = []
|
LOCK.acquire()
|
||||||
EHS_MSG = []
|
stream.process_raw(ADSB_TS, ADSB_MSG, COMMB_TS, COMMB_MSG)
|
||||||
EHS_TS = []
|
ADSB_MSG = []
|
||||||
LOCK.release()
|
ADSB_TS = []
|
||||||
|
COMMB_MSG = []
|
||||||
acs = stream.get_aircraft()
|
COMMB_TS = []
|
||||||
# try:
|
LOCK.release()
|
||||||
screen.update_data(acs)
|
|
||||||
screen.update()
|
acs = stream.get_aircraft()
|
||||||
# except KeyboardInterrupt:
|
try:
|
||||||
# raise
|
screen.update_data(acs)
|
||||||
# except:
|
screen.update()
|
||||||
# continue
|
except KeyboardInterrupt:
|
||||||
|
raise
|
||||||
except KeyboardInterrupt:
|
except:
|
||||||
sys.exit(0)
|
continue
|
||||||
|
|
||||||
finally:
|
except KeyboardInterrupt:
|
||||||
curses.endwin()
|
sys.exit(0)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
curses.endwin()
|
@ -1,16 +1,35 @@
|
|||||||
from __future__ import print_function, division
|
from __future__ import print_function, division
|
||||||
|
import os
|
||||||
import curses
|
import curses
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import time
|
import time
|
||||||
from threading import Thread
|
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):
|
class Screen(Thread):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
self.screen = curses.initscr()
|
self.screen = curses.initscr()
|
||||||
curses.noecho()
|
curses.noecho()
|
||||||
|
curses.mousemask(1)
|
||||||
self.screen.keypad(True)
|
self.screen.keypad(True)
|
||||||
self.y = 3
|
self.y = 3
|
||||||
self.x = 1
|
self.x = 1
|
||||||
@ -27,7 +46,7 @@ class Screen(Thread):
|
|||||||
|
|
||||||
def draw_frame(self):
|
def draw_frame(self):
|
||||||
self.screen.border(0)
|
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):
|
def update(self):
|
||||||
if len(self.acs) == 0:
|
if len(self.acs) == 0:
|
||||||
@ -44,14 +63,17 @@ class Screen(Thread):
|
|||||||
|
|
||||||
row = 1
|
row = 1
|
||||||
|
|
||||||
header = 'icao'
|
header = ' icao'
|
||||||
for c in COLUMNS:
|
for c, cw in COLUMNS:
|
||||||
c = 'updated' if c=='t' else c
|
header += (cw-len(c))*' ' + c
|
||||||
header += '%10s' % c
|
|
||||||
|
# fill end with spaces
|
||||||
|
header += (self.scr_w - 2 - len(header)) * ' '
|
||||||
|
|
||||||
if len(header) > self.scr_w - 2:
|
if len(header) > self.scr_w - 2:
|
||||||
header = header[:self.scr_w-3] + '>'
|
header = header[:self.scr_w-3] + '>'
|
||||||
|
|
||||||
|
|
||||||
self.screen.addstr(row, 1, header)
|
self.screen.addstr(row, 1, header)
|
||||||
|
|
||||||
row +=1
|
row +=1
|
||||||
@ -74,19 +96,23 @@ class Screen(Thread):
|
|||||||
|
|
||||||
line += icao
|
line += icao
|
||||||
|
|
||||||
for c in COLUMNS:
|
for c, cw in COLUMNS:
|
||||||
|
if c=='live':
|
||||||
if c == 't':
|
val = int(time.time() - ac[c])
|
||||||
val = str(int(ac[c]))
|
elif ac[c] is None:
|
||||||
line += '%12s' % val
|
val = ''
|
||||||
else:
|
else:
|
||||||
val = '' if ac[c] is None else ac[c]
|
val = ac[c]
|
||||||
line += '%10s' % val
|
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:
|
if len(line) > self.scr_w - 2:
|
||||||
line = line[:self.scr_w-3] + '>'
|
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)
|
self.screen.addstr(row, 1, line, curses.A_STANDOUT)
|
||||||
elif row == self.y:
|
elif row == self.y:
|
||||||
self.screen.addstr(row, 1, line, curses.A_BOLD)
|
self.screen.addstr(row, 1, line, curses.A_BOLD)
|
||||||
@ -108,7 +134,10 @@ class Screen(Thread):
|
|||||||
while True:
|
while True:
|
||||||
c = self.screen.getch()
|
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.x = 1
|
||||||
self.y = 1
|
self.y = 1
|
||||||
elif c == curses.KEY_NPAGE:
|
elif c == curses.KEY_NPAGE:
|
||||||
@ -131,3 +160,6 @@ class Screen(Thread):
|
|||||||
self.y = y_intent
|
self.y = y_intent
|
||||||
elif c == curses.KEY_ENTER or c == 10 or c == 13:
|
elif c == curses.KEY_ENTER or c == 10 or c == 13:
|
||||||
self.lock_icao = (self.screen.instr(self.y, 1, 6)).decode()
|
self.lock_icao = (self.screen.instr(self.y, 1, 6)).decode()
|
||||||
|
elif c == curses.KEY_F5:
|
||||||
|
self.screen.refresh()
|
||||||
|
self.draw_frame()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from __future__ import absolute_import, print_function, division
|
from __future__ import absolute_import, print_function, division
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import time
|
import time
|
||||||
from pyModeS.decoder import adsb, ehs
|
import pyModeS as pms
|
||||||
|
|
||||||
class Stream():
|
class Stream():
|
||||||
def __init__(self, lat0, lon0):
|
def __init__(self, lat0, lon0):
|
||||||
@ -18,8 +18,8 @@ class Stream():
|
|||||||
self.cache_timeout = 60 # seconds
|
self.cache_timeout = 60 # seconds
|
||||||
|
|
||||||
|
|
||||||
def process_raw(self, adsb_ts, adsb_msgs, ehs_ts, ehs_msgs, tnow=None):
|
def process_raw(self, adsb_ts, adsb_msgs, commb_ts, commb_msgs, tnow=None):
|
||||||
"""process a chunk of adsb and ehs messages recieved in the same
|
"""process a chunk of adsb and commb messages recieved in the same
|
||||||
time period.
|
time period.
|
||||||
"""
|
"""
|
||||||
if tnow is None:
|
if tnow is None:
|
||||||
@ -31,11 +31,12 @@ class Stream():
|
|||||||
|
|
||||||
# process adsb message
|
# process adsb message
|
||||||
for t, msg in zip(adsb_ts, adsb_msgs):
|
for t, msg in zip(adsb_ts, adsb_msgs):
|
||||||
icao = adsb.icao(msg)
|
icao = pms.icao(msg)
|
||||||
tc = adsb.typecode(msg)
|
tc = pms.adsb.typecode(msg)
|
||||||
|
|
||||||
if icao not in self.acs:
|
if icao not in self.acs:
|
||||||
self.acs[icao] = {
|
self.acs[icao] = {
|
||||||
|
'live': None,
|
||||||
'lat': None,
|
'lat': None,
|
||||||
'lon': None,
|
'lon': None,
|
||||||
'alt': None,
|
'alt': None,
|
||||||
@ -46,20 +47,20 @@ class Stream():
|
|||||||
'ias': None,
|
'ias': None,
|
||||||
'mach': None,
|
'mach': None,
|
||||||
'hdg': None,
|
'hdg': None,
|
||||||
'adsb_version' : None,
|
'ver' : None,
|
||||||
'nic_s' : None,
|
'NIC' : None,
|
||||||
'nic_a' : None,
|
'NACp' : None,
|
||||||
'nic_b' : None,
|
'NACv' : None,
|
||||||
'nic_c' : None
|
'SIL' : None
|
||||||
}
|
}
|
||||||
|
|
||||||
self.acs[icao]['t'] = t
|
self.acs[icao]['live'] = int(t)
|
||||||
|
|
||||||
if 1 <= tc <= 4:
|
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):
|
if (5 <= tc <= 8) or (tc == 19):
|
||||||
vdata = adsb.velocity(msg)
|
vdata = pms.adsb.velocity(msg)
|
||||||
if vdata is None:
|
if vdata is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ class Stream():
|
|||||||
self.acs[icao]['tv'] = t
|
self.acs[icao]['tv'] = t
|
||||||
|
|
||||||
if (5 <= tc <= 18):
|
if (5 <= tc <= 18):
|
||||||
oe = adsb.oe_flag(msg)
|
oe = pms.adsb.oe_flag(msg)
|
||||||
self.acs[icao][oe] = msg
|
self.acs[icao][oe] = msg
|
||||||
self.acs[icao]['t'+str(oe)] = t
|
self.acs[icao]['t'+str(oe)] = t
|
||||||
|
|
||||||
@ -83,21 +84,21 @@ class Stream():
|
|||||||
# use single message decoding
|
# use single message decoding
|
||||||
rlat = self.acs[icao]['lat']
|
rlat = self.acs[icao]['lat']
|
||||||
rlon = self.acs[icao]['lon']
|
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 \
|
elif ('t0' in self.acs[icao]) and ('t1' in self.acs[icao]) and \
|
||||||
(abs(self.acs[icao]['t0'] - self.acs[icao]['t1']) < 10):
|
(abs(self.acs[icao]['t0'] - self.acs[icao]['t1']) < 10):
|
||||||
# use multi message decoding
|
# use multi message decoding
|
||||||
try:
|
# try:
|
||||||
latlon = adsb.position(
|
latlon = pms.adsb.position(
|
||||||
self.acs[icao][0],
|
self.acs[icao][0],
|
||||||
self.acs[icao][1],
|
self.acs[icao][1],
|
||||||
self.acs[icao]['t0'],
|
self.acs[icao]['t0'],
|
||||||
self.acs[icao]['t1'],
|
self.acs[icao]['t1'],
|
||||||
self.lat0, self.lon0
|
self.lat0, self.lon0
|
||||||
)
|
)
|
||||||
except:
|
# except:
|
||||||
# mix of surface and airborne position message
|
# # mix of surface and airborne position message
|
||||||
continue
|
# continue
|
||||||
else:
|
else:
|
||||||
latlon = None
|
latlon = None
|
||||||
|
|
||||||
@ -105,71 +106,60 @@ class Stream():
|
|||||||
self.acs[icao]['tpos'] = t
|
self.acs[icao]['tpos'] = t
|
||||||
self.acs[icao]['lat'] = latlon[0]
|
self.acs[icao]['lat'] = latlon[0]
|
||||||
self.acs[icao]['lon'] = latlon[1]
|
self.acs[icao]['lon'] = latlon[1]
|
||||||
|
<<<<<<< HEAD
|
||||||
self.acs[icao]['alt'] = adsb.altitude(msg)
|
self.acs[icao]['alt'] = adsb.altitude(msg)
|
||||||
# local_updated_acs_buffer.append(icao)acs[icao]['adsb_version']
|
# local_updated_acs_buffer.append(icao)acs[icao]['adsb_version']
|
||||||
local_updated_acs_buffer.append(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
|
# Uncertainty & accuracy
|
||||||
if (5 <= tc <= 8):
|
ac = self.acs[icao]
|
||||||
if self.acs[icao]['adsb_version'] == 1:
|
|
||||||
if self.acs[icao]['nic_s'] != None:
|
if (5 <= tc <= 8) or (9 <= tc <= 18) or (20 <= tc <= 22):
|
||||||
self.nic = adsb.nic_v1(msg,self.acs[icao]['nic_s'])
|
if (ac['ver'] == 1) and ('nic_s' in ac.keys()):
|
||||||
elif self.acs[icao]['adsb_version'] == 2:
|
self.acs[icao]['NIC'] = pms.adsb.nic_v1(msg, ac['nic_s'])
|
||||||
if self.acs[icao]['nic_a'] != None and self.acs[icao]['nic_b'] != None:
|
elif (ac['ver'] == 2) and ('nic_a' in ac.keys()) and ('nic_b' in ac.keys()):
|
||||||
self.nic = adsb.nic_v2(msg,self.nic_a,self.acs[icao]['nic_b'],self.acs[icao]['nic_c'])
|
self.acs[icao]['NIC'] = pms.adsb.nic_v2(msg, ac['nic_a'], ac['nic_b'], ac['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'])
|
|
||||||
if tc == 19:
|
if tc == 19:
|
||||||
self.acs[icao]['nac_v'] = adsb.nac_v(msg)
|
if ac['ver'] in [1, 2]:
|
||||||
if (20 <= tc <= 22):
|
self.acs[icao]['NACv'] = pms.adsb.nac_v(msg)
|
||||||
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 tc == 29:
|
if tc == 29:
|
||||||
if self.acs[icao]['adsb_version'] != None:
|
if ac['ver'] != None:
|
||||||
self.acs[icao]['sil'] = adsb.sil(msg,self.acs[icao]['adsb_version'])
|
self.acs[icao]['SIL'], self.acs[icao]['sil_s'] = pms.adsb.sil(msg, ac['ver'])
|
||||||
self.acs[icao]['nac_p'] = adsb.nac_p(msg)
|
self.acs[icao]['NACp'] = pms.adsb.nac_p(msg)
|
||||||
if tc == 31:
|
if tc == 31:
|
||||||
self.acs[icao]['adsb_version'] = adsb.version(msg)
|
self.acs[icao]['ver'] = pms.adsb.version(msg)
|
||||||
self.acs[icao]['sil'] = adsb.version(msg)
|
self.acs[icao]['SIL'] = pms.adsb.version(msg)
|
||||||
self.acs[icao]['nac_p'] = adsb.nac_p(msg)
|
self.acs[icao]['NACp'] = pms.adsb.nac_p(msg)
|
||||||
if self.acs[icao]['adsb_version'] == 1:
|
if self.acs[icao]['ver'] == 1:
|
||||||
self.acs[icao]['nic_s'] = adsb.nic_s(msg)
|
self.acs[icao]['nic_s'] = pms.adsb.nic_s(msg)
|
||||||
elif self.acs[icao]['adsb_version'] == 2:
|
elif self.acs[icao]['ver'] == 2:
|
||||||
self.acs[icao]['nic_a'] , self.acs[icao]['nic_c'] = adsb.nic_a_and_c(msg)
|
self.acs[icao]['nic_a'], self.acs[icao]['nic_c'] = pms.adsb.nic_a_c(msg)
|
||||||
|
|
||||||
|
|
||||||
|
# process commb message
|
||||||
|
for t, msg in zip(commb_ts, commb_msgs):
|
||||||
# process ehs message
|
icao = pms.icao(msg)
|
||||||
for t, msg in zip(ehs_ts, ehs_msgs):
|
|
||||||
icao = ehs.icao(msg)
|
|
||||||
|
|
||||||
if icao not in self.acs:
|
if icao not in self.acs:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
bds = ehs.BDS(msg)
|
bds = pms.bds.infer(msg)
|
||||||
|
|
||||||
if bds == 'BDS50':
|
if bds == 'BDS50':
|
||||||
tas = ehs.tas50(msg)
|
tas = pms.commb.tas50(msg)
|
||||||
|
|
||||||
if tas:
|
if tas:
|
||||||
self.acs[icao]['t50'] = t
|
self.acs[icao]['t50'] = t
|
||||||
self.acs[icao]['tas'] = tas
|
self.acs[icao]['tas'] = tas
|
||||||
|
|
||||||
elif bds == 'BDS60':
|
elif bds == 'BDS60':
|
||||||
ias = ehs.ias60(msg)
|
ias = pms.commb.ias60(msg)
|
||||||
hdg = ehs.hdg60(msg)
|
hdg = pms.commb.hdg60(msg)
|
||||||
mach = ehs.mach60(msg)
|
mach = pms.commb.mach60(msg)
|
||||||
|
|
||||||
if ias or hdg or mach:
|
if ias or hdg or mach:
|
||||||
self.acs[icao]['t60'] = t
|
self.acs[icao]['t60'] = t
|
||||||
@ -182,7 +172,7 @@ class Stream():
|
|||||||
|
|
||||||
# clear up old data
|
# clear up old data
|
||||||
for icao in list(self.acs.keys()):
|
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]
|
del self.acs[icao]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -214,4 +204,4 @@ class Stream():
|
|||||||
|
|
||||||
def reset_new_aircraft(self):
|
def reset_new_aircraft(self):
|
||||||
"""reset the updated icao buffer once been read"""
|
"""reset the updated icao buffer once been read"""
|
||||||
self.__new_acs = set()
|
self.__new_acs = set()
|
||||||
|
Loading…
Reference in New Issue
Block a user