Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7267859548 | ||
|
|
7a3bd089c4 | ||
|
|
17fdaca1c7 | ||
|
|
6f6b50776d | ||
|
|
0b7b9ad3dd | ||
|
|
24806f7e88 | ||
|
|
57ad40ec57 | ||
|
|
d230bdc4a9 | ||
|
|
4a6d3334a7 | ||
|
|
9f371fe86b | ||
|
|
0ea4969393 | ||
|
|
312c77629b | ||
|
|
6159691c3d | ||
|
|
7edbf3fd30 | ||
|
|
e19d0cd945 | ||
|
|
6fc68841ce | ||
|
|
f27fe6c8aa | ||
|
|
81a46e5070 | ||
|
|
6c2adbe990 | ||
|
|
3c14579040 | ||
|
|
fc9b05b6f1 | ||
|
|
b813e41343 | ||
|
|
c9159feb7d | ||
|
|
8cd5655a04 | ||
|
|
8ded3500d4 | ||
|
|
c348a2295d | ||
|
|
040a1879c9 | ||
|
|
61b55531e8 | ||
|
|
abdafd7dea | ||
|
|
b97299ce1b | ||
|
|
652ef65bbb | ||
|
|
bfdb8221a0 | ||
|
|
32e6ee3904 | ||
|
|
d82dfd5537 |
133
README.rst
133
README.rst
@@ -1,7 +1,26 @@
|
||||
The Python ADS-B/Mode-S Decoder
|
||||
==========================================
|
||||
===============================
|
||||
|
||||
If you find this project useful for your research, please cite our work (bibtex format):
|
||||
|
||||
::
|
||||
|
||||
@article{sun2019pymodes,
|
||||
author={J. {Sun} and H. {V\^u} and J. {Ellerbroek} and J. M. {Hoekstra}},
|
||||
journal={IEEE Transactions on Intelligent Transportation Systems},
|
||||
title={pyModeS: Decoding Mode-S Surveillance Data for Open Air Transportation Research},
|
||||
year={2019},
|
||||
doi={10.1109/TITS.2019.2914770},
|
||||
ISSN={1524-9050},
|
||||
}
|
||||
|
||||
|
||||
|
||||
Introduction
|
||||
---------------------
|
||||
PyModeS is a Python library designed to decode Mode-S (including ADS-B) message.
|
||||
Message with following Downlink Formats (DF) are supported:
|
||||
|
||||
Python library for ADS-B/Mode-S message decoding. Supported Downlink Formats (DF) are:
|
||||
|
||||
**DF17 / DF18: Automatic Dependent Surveillance - Broadcast (ADS-B)**
|
||||
|
||||
@@ -19,12 +38,11 @@ Python library for ADS-B/Mode-S message decoding. Supported Downlink Formats (DF
|
||||
- BDS 1,0: Data link capability report
|
||||
- BDS 1,7: Common usage GICB capability report
|
||||
- BDS 2,0: Aircraft identification
|
||||
- BDS 2,1: Aircraft and airline registration markings
|
||||
- BDS 3,0: ACAS active resolution advisory
|
||||
- BDS 4,0: Selected vertical intention
|
||||
- BDS 4,4: Meteorological routine air report
|
||||
- BDS 4,4: Meteorological routine air report (experimental)
|
||||
- BDS 4,5: Meteorological hazard report (experimental)
|
||||
- BDS 5,0: Track and turn report
|
||||
- BDS 5,3: Air-referenced state vector
|
||||
- BDS 6,0: Heading and speed report
|
||||
|
||||
|
||||
@@ -32,27 +50,18 @@ Python library for ADS-B/Mode-S message decoding. Supported Downlink Formats (DF
|
||||
|
||||
**DF5 / DF21: Identity code (squawk code)**
|
||||
|
||||
Detailed manual on Mode-S decoding is published by the author, at:
|
||||
https://mode-s.org/decode
|
||||
|
||||
|
||||
New features in v2.0
|
||||
---------------------
|
||||
- New structure of the libraries
|
||||
- ADS-B and Comm-B data streaming
|
||||
- Active aircraft viewing (terminal curses)
|
||||
- Improved BDS identification
|
||||
- Optimizing decoding speed
|
||||
|
||||
|
||||
Source code
|
||||
Resources
|
||||
-----------
|
||||
Checkout and contribute to this open-source project at:
|
||||
https://github.com/junzis/pyModeS
|
||||
|
||||
API documentation at:
|
||||
Detailed manual on Mode-S decoding is published at:
|
||||
https://mode-s.org/decode.
|
||||
|
||||
API documentation of pyModeS is at:
|
||||
http://pymodes.readthedocs.io
|
||||
[To be updated]
|
||||
|
||||
|
||||
|
||||
Install
|
||||
@@ -102,6 +111,7 @@ Example screenshot:
|
||||
.. image:: https://github.com/junzis/pyModeS/raw/master/doc/modeslive-screenshot.png
|
||||
:width: 700px
|
||||
|
||||
|
||||
Use the library
|
||||
---------------
|
||||
|
||||
@@ -214,19 +224,19 @@ Mode-S Enhanced Surveillance (EHS)
|
||||
|
||||
.. code:: python
|
||||
|
||||
# For BDS register 4,0
|
||||
pms.commb.alt40mcp(msg) # MCP/FCU selected altitude (ft)
|
||||
pms.commb.alt40fms(msg) # FMS selected altitude (ft)
|
||||
# BDS 4,0
|
||||
pms.commb.selalt40mcp(msg) # MCP/FCU selected altitude (ft)
|
||||
pms.commb.selalt40fms(msg) # FMS selected altitude (ft)
|
||||
pms.commb.p40baro(msg) # Barometric pressure (mb)
|
||||
|
||||
# For BDS register 5,0
|
||||
# BDS 5,0
|
||||
pms.commb.roll50(msg) # Roll angle (deg)
|
||||
pms.commb.trk50(msg) # True track angle (deg)
|
||||
pms.commb.gs50(msg) # Ground speed (kt)
|
||||
pms.commb.rtrk50(msg) # Track angle rate (deg/sec)
|
||||
pms.commb.tas50(msg) # True airspeed (kt)
|
||||
|
||||
# For BDS register 6,0
|
||||
# BDS 6,0
|
||||
pms.commb.hdg60(msg) # Magnetic heading (deg)
|
||||
pms.commb.ias60(msg) # Indicated airspeed (kt)
|
||||
pms.commb.mach60(msg) # Mach number (-)
|
||||
@@ -235,19 +245,78 @@ Mode-S Enhanced Surveillance (EHS)
|
||||
|
||||
|
||||
Meteorological routine air report (MRAR) [Experimental]
|
||||
********************************************************
|
||||
|
||||
.. code:: python
|
||||
|
||||
# BDS 4,4
|
||||
pms.commb.wind44(msg) # Wind speed (kt) and direction (true) (deg)
|
||||
pms.commb.temp44(msg) # Static air temperature (C)
|
||||
pms.commb.p44(msg) # Average static pressure (hPa)
|
||||
pms.commb.hum44(msg) # Humidity (%)
|
||||
|
||||
|
||||
Meteorological hazard air report (MHR) [Experimental]
|
||||
*******************************************************
|
||||
|
||||
.. code:: python
|
||||
|
||||
# For BDS register 4,4
|
||||
pms.commb.wind44(msg, rev=False) # Wind speed (kt) and direction (true) (deg)
|
||||
pms.commb.temp44(msg, rev=False) # Static air temperature (C)
|
||||
pms.commb.p44(msg, rev=False) # Average static pressure (hPa)
|
||||
pms.commb.hum44(msg, rev=False) # Humidity (%)
|
||||
# BDS 4,5
|
||||
pms.commb.turb45(msg) # Turbulence level (0-3)
|
||||
pms.commb.ws45(msg) # Wind shear level (0-3)
|
||||
pms.commb.mb45(msg) # Microburst level (0-3)
|
||||
pms.commb.ic45(msg) # Icing level (0-3)
|
||||
pms.commb.wv45(msg) # Wake vortex level (0-3)
|
||||
pms.commb.temp45(msg) # Static air temperature (C)
|
||||
pms.commb.p45(msg) # Average static pressure (hPa)
|
||||
pms.commb.rh45(msg) # Radio height (ft)
|
||||
|
||||
|
||||
Developement
|
||||
------------
|
||||
|
||||
Customize the streaming module
|
||||
******************************
|
||||
The TCP client module from pyModeS can be re-used to stream and process Mode-S
|
||||
data as your like. You need to re-implement the ``handle_messages()`` function from
|
||||
the ``BaseClient`` class to write your own logic to handle the messages.
|
||||
|
||||
Here is an example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from pyModeS.extra.tcpclient import BaseClient
|
||||
|
||||
# define your custom class by extending the BaseClient
|
||||
# - implement your handle_messages() methods
|
||||
class ADSBClient(BaseClient):
|
||||
def __init__(self, host, port, rawtype):
|
||||
super(ModesClient, self).__init__(host, port, rawtype)
|
||||
|
||||
def handle_messages(self, messages):
|
||||
for msg, ts in messages:
|
||||
if len(msg) < 28: # wrong data length
|
||||
continue
|
||||
|
||||
df = pms.df(msg)
|
||||
|
||||
if df != 17: # not ADSB
|
||||
continue
|
||||
|
||||
if '1' in pms.crc(msg): # CRC fail
|
||||
continue
|
||||
|
||||
icao = pms.adsb.icao(msg)
|
||||
tc = pms.adsb.typecode(msg)
|
||||
|
||||
# TODO: write you magic code here
|
||||
print ts, icao, tc, msg
|
||||
|
||||
# run new client, change the host, port, and rawtype if needed
|
||||
client = ADSBClient(host='127.0.0.1', port=30334, rawtype='beast')
|
||||
client.run()
|
||||
|
||||
|
||||
Unit test
|
||||
---------
|
||||
To perform unit tests. First install ``tox`` through pip, Then, run the following commands:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
3
doc/.gitignore
vendored
3
doc/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
_build
|
||||
_static
|
||||
_templates
|
||||
228
doc/Makefile
228
doc/Makefile
@@ -1,225 +1,21 @@
|
||||
# Makefile for Sphinx documentation
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " applehelp to make an Apple Help Book"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " epub3 to make an epub3"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " xml to make Docutils-native XML files"
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
@echo " coverage to run coverage check of the documentation (if enabled)"
|
||||
@echo " dummy to check syntax errors of document sources"
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
.PHONY: help Makefile
|
||||
|
||||
.PHONY: html
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
.PHONY: dirhtml
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
.PHONY: singlehtml
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
.PHONY: pickle
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
.PHONY: json
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
.PHONY: htmlhelp
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
.PHONY: qthelp
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pyModeS.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pyModeS.qhc"
|
||||
|
||||
.PHONY: applehelp
|
||||
applehelp:
|
||||
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
|
||||
@echo
|
||||
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
|
||||
@echo "N.B. You won't be able to view it unless you put it in" \
|
||||
"~/Library/Documentation/Help or install it in your application" \
|
||||
"bundle."
|
||||
|
||||
.PHONY: devhelp
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/pyModeS"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pyModeS"
|
||||
@echo "# devhelp"
|
||||
|
||||
.PHONY: epub
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
.PHONY: epub3
|
||||
epub3:
|
||||
$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
|
||||
@echo
|
||||
@echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
|
||||
|
||||
.PHONY: latex
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
.PHONY: latexpdf
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
.PHONY: latexpdfja
|
||||
latexpdfja:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
.PHONY: text
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
.PHONY: man
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
.PHONY: texinfo
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
.PHONY: info
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
.PHONY: gettext
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
.PHONY: changes
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
.PHONY: linkcheck
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
.PHONY: doctest
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
|
||||
@echo "Testing of coverage in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/coverage/python.txt."
|
||||
|
||||
.PHONY: xml
|
||||
xml:
|
||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||
@echo
|
||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||
|
||||
.PHONY: pseudoxml
|
||||
pseudoxml:
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
||||
|
||||
.PHONY: dummy
|
||||
dummy:
|
||||
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
|
||||
@echo
|
||||
@echo "Build finished. Dummy builder generates no files."
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
rm -f source/pyModeS*.rst source/modules.rst
|
||||
sphinx-apidoc -f -e -M -o source/ ../pyModeS
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
7
doc/README.rst
Normal file
7
doc/README.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
How to generate the apidoc
|
||||
====================================
|
||||
|
||||
::
|
||||
|
||||
cd doc
|
||||
make html
|
||||
337
doc/conf.py
337
doc/conf.py
@@ -1,337 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# pyModeS documentation build configuration file, created by
|
||||
# sphinx-quickstart on Tue Aug 16 15:47:05 2016.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'pyModeS'
|
||||
copyright = u'2016, Junzi Sun'
|
||||
author = u'Junzi Sun'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = u'1.0.5'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'1.0.5'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#
|
||||
# today = ''
|
||||
#
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#
|
||||
# today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#
|
||||
# default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#
|
||||
# add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#
|
||||
# add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
# keep_warnings = False
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = True
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
# html_theme = 'alabaster'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
# html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents.
|
||||
# "<project> v<release> documentation" by default.
|
||||
#
|
||||
# html_title = u'pyModeS v1.0.5'
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#
|
||||
# html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#
|
||||
# html_logo = None
|
||||
|
||||
# The name of an image file (relative to this directory) to use as a favicon of
|
||||
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#
|
||||
# html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
#
|
||||
# html_extra_path = []
|
||||
|
||||
# If not None, a 'Last updated on:' timestamp is inserted at every page
|
||||
# bottom, using the given strftime format.
|
||||
# The empty string is equivalent to '%b %d, %Y'.
|
||||
#
|
||||
# html_last_updated_fmt = None
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#
|
||||
# html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#
|
||||
# html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#
|
||||
# html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#
|
||||
# html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#
|
||||
# html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#
|
||||
# html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#
|
||||
# html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#
|
||||
# html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#
|
||||
# html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
# html_file_suffix = None
|
||||
|
||||
# Language to be used for generating the HTML full-text search index.
|
||||
# Sphinx supports the following languages:
|
||||
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
|
||||
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
|
||||
#
|
||||
# html_search_language = 'en'
|
||||
|
||||
# A dictionary with options for the search language support, empty by default.
|
||||
# 'ja' uses this config value.
|
||||
# 'zh' user can custom change `jieba` dictionary path.
|
||||
#
|
||||
# html_search_options = {'type': 'default'}
|
||||
|
||||
# The name of a javascript file (relative to the configuration directory) that
|
||||
# implements a search results scorer. If empty, the default will be used.
|
||||
#
|
||||
# html_search_scorer = 'scorer.js'
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'pyModeSdoc'
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'pyModeS.tex', u'pyModeS Documentation',
|
||||
u'Junzi Sun', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#
|
||||
# latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#
|
||||
# latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#
|
||||
# latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#
|
||||
# latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#
|
||||
# latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#
|
||||
# latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'pymodes', u'pyModeS Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#
|
||||
# man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'pyModeS', u'pyModeS Documentation',
|
||||
author, 'pyModeS', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#
|
||||
# texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#
|
||||
# texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#
|
||||
# texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#
|
||||
# texinfo_no_detailmenu = False
|
||||
@@ -1,40 +0,0 @@
|
||||
.. pyModeS documentation master file, created by
|
||||
sphinx-quickstart on Tue Aug 16 15:47:05 2016.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
|
||||
pyModeS APIs
|
||||
=====================
|
||||
|
||||
This document contains all the functions within pyModeS package.
|
||||
|
||||
Source code and user guide: https://github.com/junzis/pyModeS
|
||||
|
||||
|
||||
pyModeS.adsb module
|
||||
-------------------
|
||||
|
||||
.. automodule:: pyModeS.adsb
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
pyModeS.ehs module
|
||||
------------------
|
||||
|
||||
.. automodule:: pyModeS.ehs
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
pyModeS.util module
|
||||
-------------------
|
||||
|
||||
.. automodule:: pyModeS.util
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
pyModeS==1.1.0
|
||||
188
doc/source/conf.py
Normal file
188
doc/source/conf.py
Normal file
@@ -0,0 +1,188 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# full list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath('../..'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'pyModeS'
|
||||
copyright = '2019, Junzi Sun'
|
||||
author = 'Junzi Sun'
|
||||
|
||||
# The short X.Y version
|
||||
version = ''
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = ''
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.githubpages',
|
||||
'sphinx.ext.napoleon',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
# templates_path = ['']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = None
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
# html_theme = 'alabaster'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
# html_static_path = ['']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# The default sidebars (for documents that don't match any pattern) are
|
||||
# defined by theme itself. Builtin themes are using these templates by
|
||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
||||
# 'searchbox.html']``.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ---------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'pyModeSdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'pyModeS.tex', 'pyModeS Documentation',
|
||||
'Junzi Sun', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'pymodes', 'pyModeS Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output ----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'pyModeS', 'pyModeS Documentation',
|
||||
author, 'pyModeS', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Epub output -------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = project
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#
|
||||
# epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#
|
||||
# epub_uid = ''
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
||||
|
||||
|
||||
# -- Extension configuration -------------------------------------------------
|
||||
|
||||
# -- Options for todo extension ----------------------------------------------
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = True
|
||||
30
doc/source/index.rst
Normal file
30
doc/source/index.rst
Normal file
@@ -0,0 +1,30 @@
|
||||
.. pyModeS documentation master file, created by
|
||||
sphinx-quickstart on Mon Apr 1 13:13:10 2019.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to pyModeS documentation!
|
||||
===================================
|
||||
|
||||
The source code can be found at: https://github.com/junzis/pyModeS
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
pyModeS.decoder
|
||||
pyModeS.streamer
|
||||
pyModeS.extra
|
||||
|
||||
|
||||
----
|
||||
|
||||
.. include:: ../../README.rst
|
||||
|
||||
----
|
||||
|
||||
Indices and tables
|
||||
**********************
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
35
doc/source/make.bat
Normal file
35
doc/source/make.bat
Normal file
@@ -0,0 +1,35 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
||||
7
doc/source/modules.rst
Normal file
7
doc/source/modules.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS
|
||||
=======
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
pyModeS
|
||||
7
doc/source/pyModeS.decoder.acas.rst
Normal file
7
doc/source/pyModeS.decoder.acas.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.acas module
|
||||
===========================
|
||||
|
||||
.. automodule:: pyModeS.decoder.acas
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.adsb.rst
Normal file
7
doc/source/pyModeS.decoder.adsb.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.adsb module
|
||||
===========================
|
||||
|
||||
.. automodule:: pyModeS.decoder.adsb
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.allcall.rst
Normal file
7
doc/source/pyModeS.decoder.allcall.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.allcall module
|
||||
==============================
|
||||
|
||||
.. automodule:: pyModeS.decoder.allcall
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds05.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds05.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds05 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds05
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds06.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds06.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds06 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds06
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds08.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds08.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds08 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds08
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds09.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds09.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds09 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds09
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds10.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds10.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds10 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds10
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds17.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds17.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds17 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds17
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds20.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds20.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds20 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds20
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds30.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds30.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds30 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds30
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds40.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds40.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds40 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds40
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds44.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds44.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds44 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds44
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds45.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds45.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds45 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds45
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds50.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds50.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds50 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds50
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds53.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds53.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds53 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds53
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.bds.bds60.rst
Normal file
7
doc/source/pyModeS.decoder.bds.bds60.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.bds.bds60 module
|
||||
================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds.bds60
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
28
doc/source/pyModeS.decoder.bds.rst
Normal file
28
doc/source/pyModeS.decoder.bds.rst
Normal file
@@ -0,0 +1,28 @@
|
||||
pyModeS.decoder.bds package
|
||||
===========================
|
||||
|
||||
.. automodule:: pyModeS.decoder.bds
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
.. toctree::
|
||||
|
||||
pyModeS.decoder.bds.bds05
|
||||
pyModeS.decoder.bds.bds06
|
||||
pyModeS.decoder.bds.bds08
|
||||
pyModeS.decoder.bds.bds09
|
||||
pyModeS.decoder.bds.bds10
|
||||
pyModeS.decoder.bds.bds17
|
||||
pyModeS.decoder.bds.bds20
|
||||
pyModeS.decoder.bds.bds30
|
||||
pyModeS.decoder.bds.bds40
|
||||
pyModeS.decoder.bds.bds44
|
||||
pyModeS.decoder.bds.bds45
|
||||
pyModeS.decoder.bds.bds50
|
||||
pyModeS.decoder.bds.bds53
|
||||
pyModeS.decoder.bds.bds60
|
||||
|
||||
7
doc/source/pyModeS.decoder.commb.rst
Normal file
7
doc/source/pyModeS.decoder.commb.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.commb module
|
||||
============================
|
||||
|
||||
.. automodule:: pyModeS.decoder.commb
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.common.rst
Normal file
7
doc/source/pyModeS.decoder.common.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.common module
|
||||
=============================
|
||||
|
||||
.. automodule:: pyModeS.decoder.common
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.ehs.rst
Normal file
7
doc/source/pyModeS.decoder.ehs.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.ehs module
|
||||
==========================
|
||||
|
||||
.. automodule:: pyModeS.decoder.ehs
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.els.rst
Normal file
7
doc/source/pyModeS.decoder.els.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.els module
|
||||
==========================
|
||||
|
||||
.. automodule:: pyModeS.decoder.els
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
30
doc/source/pyModeS.decoder.rst
Normal file
30
doc/source/pyModeS.decoder.rst
Normal file
@@ -0,0 +1,30 @@
|
||||
pyModeS.decoder package
|
||||
=======================
|
||||
|
||||
.. automodule:: pyModeS.decoder
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
|
||||
pyModeS.decoder.bds
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
.. toctree::
|
||||
|
||||
pyModeS.decoder.acas
|
||||
pyModeS.decoder.adsb
|
||||
pyModeS.decoder.allcall
|
||||
pyModeS.decoder.commb
|
||||
pyModeS.decoder.common
|
||||
pyModeS.decoder.ehs
|
||||
pyModeS.decoder.els
|
||||
pyModeS.decoder.surv
|
||||
pyModeS.decoder.uncertainty
|
||||
|
||||
7
doc/source/pyModeS.decoder.surv.rst
Normal file
7
doc/source/pyModeS.decoder.surv.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.surv module
|
||||
===========================
|
||||
|
||||
.. automodule:: pyModeS.decoder.surv
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.decoder.uncertainty.rst
Normal file
7
doc/source/pyModeS.decoder.uncertainty.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.decoder.uncertainty module
|
||||
==================================
|
||||
|
||||
.. automodule:: pyModeS.decoder.uncertainty
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.extra.aero.rst
Normal file
7
doc/source/pyModeS.extra.aero.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.extra.aero module
|
||||
=========================
|
||||
|
||||
.. automodule:: pyModeS.extra.aero
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
16
doc/source/pyModeS.extra.rst
Normal file
16
doc/source/pyModeS.extra.rst
Normal file
@@ -0,0 +1,16 @@
|
||||
pyModeS.extra package
|
||||
=====================
|
||||
|
||||
.. automodule:: pyModeS.extra
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
.. toctree::
|
||||
|
||||
pyModeS.extra.aero
|
||||
pyModeS.extra.tcpclient
|
||||
|
||||
7
doc/source/pyModeS.extra.tcpclient.rst
Normal file
7
doc/source/pyModeS.extra.tcpclient.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.extra.tcpclient module
|
||||
==============================
|
||||
|
||||
.. automodule:: pyModeS.extra.tcpclient
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
17
doc/source/pyModeS.rst
Normal file
17
doc/source/pyModeS.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
pyModeS package
|
||||
===============
|
||||
|
||||
.. automodule:: pyModeS
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
|
||||
pyModeS.decoder
|
||||
pyModeS.extra
|
||||
pyModeS.streamer
|
||||
|
||||
16
doc/source/pyModeS.streamer.rst
Normal file
16
doc/source/pyModeS.streamer.rst
Normal file
@@ -0,0 +1,16 @@
|
||||
pyModeS.streamer package
|
||||
========================
|
||||
|
||||
.. automodule:: pyModeS.streamer
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
.. toctree::
|
||||
|
||||
pyModeS.streamer.screen
|
||||
pyModeS.streamer.stream
|
||||
|
||||
7
doc/source/pyModeS.streamer.screen.rst
Normal file
7
doc/source/pyModeS.streamer.screen.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.streamer.screen module
|
||||
==============================
|
||||
|
||||
.. automodule:: pyModeS.streamer.screen
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
7
doc/source/pyModeS.streamer.stream.rst
Normal file
7
doc/source/pyModeS.streamer.stream.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pyModeS.streamer.stream module
|
||||
==============================
|
||||
|
||||
.. automodule:: pyModeS.streamer.stream
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
"""
|
||||
Decoding Air-Air Surveillance (ACAS) DF=0/16
|
||||
|
||||
[To be implemented]
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
|
||||
@@ -13,8 +13,19 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
The wrapper for decoding ADS-B messages
|
||||
"""ADS-B Wrapper.
|
||||
|
||||
The ADS-B wrapper also imports functions from the following modules:
|
||||
|
||||
- pyModeS.decoder.bds.bds05
|
||||
Functions: ``airborne_position``, ``airborne_position_with_ref``, ``altitude``
|
||||
- pyModeS.decoder.bds.bds06
|
||||
Functions: ``surface_position``, ``surface_position_with_ref``, ``surface_velocity``
|
||||
- pyModeS.decoder.bds.bds08
|
||||
Functions: ``category``, ``callsign``
|
||||
- pyModeS.decoder.bds.bds09
|
||||
Functions: ``airborne_velocity``, ``altitude_diff``
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
@@ -132,24 +143,36 @@ def altitude(msg):
|
||||
return None
|
||||
|
||||
|
||||
def velocity(msg):
|
||||
def velocity(msg, rtn_sources=False):
|
||||
"""Calculate the speed, heading, and vertical rate
|
||||
(handles both airborne or surface message)
|
||||
|
||||
Args:
|
||||
msg (string): 28 bytes hexadecimal message string
|
||||
rtn_source (boolean): If the function will return
|
||||
the sources for direction of travel and vertical
|
||||
rate. This will change the return value from a four
|
||||
element array to a six element array.
|
||||
|
||||
Returns:
|
||||
(int, float, int, string): speed (kt), ground track or heading (degree),
|
||||
rate of climb/descend (ft/min), and speed type
|
||||
('GS' for ground speed, 'AS' for airspeed)
|
||||
(int, float, int, string, string, string): speed (kt),
|
||||
ground track or heading (degree),
|
||||
rate of climb/descent (ft/min), speed type
|
||||
('GS' for ground speed, 'AS' for airspeed),
|
||||
direction source ('true_north' for ground track / true north
|
||||
as refrence, 'mag_north' for magnetic north as reference),
|
||||
rate of climb/descent source ('Baro' for barometer, 'GNSS'
|
||||
for GNSS constellation).
|
||||
|
||||
In the case of surface messages, None will be put in place
|
||||
for vertical rate and its respective sources.
|
||||
"""
|
||||
|
||||
if 5 <= typecode(msg) <= 8:
|
||||
return surface_velocity(msg)
|
||||
return surface_velocity(msg, rtn_sources)
|
||||
|
||||
elif typecode(msg) == 19:
|
||||
return airborne_velocity(msg)
|
||||
return airborne_velocity(msg, rtn_sources)
|
||||
|
||||
else:
|
||||
raise RuntimeError("incorrect or inconsistant message types, expecting 4<TC<9 or TC=19")
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
"""
|
||||
Decoding all call replies DF=11
|
||||
|
||||
[To be implemented]
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
|
||||
@@ -24,11 +24,11 @@ import numpy as np
|
||||
from pyModeS.extra import aero
|
||||
from pyModeS.decoder import common
|
||||
from pyModeS.decoder.bds import bds05, bds06, bds08, bds09, \
|
||||
bds10, bds17, bds20, bds30, bds40, bds44, bds50, bds53, bds60
|
||||
bds10, bds17, bds20, bds30, bds40, bds44, bds45, bds50, bds53, bds60
|
||||
|
||||
|
||||
def is50or60(msg, spd_ref, trk_ref, alt_ref):
|
||||
"""Use reference ground speed and trk to determine BDS50 and DBS60
|
||||
"""Use reference ground speed and trk to determine BDS50 and DBS60.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
@@ -38,6 +38,7 @@ def is50or60(msg, spd_ref, trk_ref, alt_ref):
|
||||
|
||||
Returns:
|
||||
String or None: BDS version, or possible versions, or None if nothing matches.
|
||||
|
||||
"""
|
||||
def vxy(v, angle):
|
||||
vx = v * np.sin(np.radians(angle))
|
||||
@@ -88,16 +89,17 @@ def is50or60(msg, spd_ref, trk_ref, alt_ref):
|
||||
return BDS
|
||||
|
||||
|
||||
def infer(msg):
|
||||
"""Estimate the most likely BDS code of an message
|
||||
def infer(msg, mrar=False):
|
||||
"""Estimate the most likely BDS code of an message.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
mrar (bool): Also infer MRAR (BDS 44) and MHR (BDS 45). Defaults to False.
|
||||
|
||||
Returns:
|
||||
String or None: BDS version, or possible versions, or None if nothing matches.
|
||||
"""
|
||||
|
||||
"""
|
||||
df = common.df(msg)
|
||||
|
||||
if common.allzeros(msg):
|
||||
@@ -124,7 +126,7 @@ def infer(msg):
|
||||
if tc == 31:
|
||||
return 'BDS65' # operational status
|
||||
|
||||
# For Comm-B replies, ELS + EHS only
|
||||
# For Comm-B replies
|
||||
IS10 = bds10.is10(msg)
|
||||
IS17 = bds17.is17(msg)
|
||||
IS20 = bds20.is20(msg)
|
||||
@@ -132,12 +134,17 @@ def infer(msg):
|
||||
IS40 = bds40.is40(msg)
|
||||
IS50 = bds50.is50(msg)
|
||||
IS60 = bds60.is60(msg)
|
||||
IS44 = bds44.is44(msg)
|
||||
IS45 = bds45.is45(msg)
|
||||
|
||||
allbds = np.array([
|
||||
"BDS10", "BDS17", "BDS20", "BDS30", "BDS40", "BDS50", "BDS60"
|
||||
])
|
||||
|
||||
mask = [IS10, IS17, IS20, IS30, IS40, IS50, IS60]
|
||||
if mrar:
|
||||
allbds = np.array(["BDS10", "BDS17", "BDS20", "BDS30", "BDS40",
|
||||
"BDS44", "BDS45", "BDS50", "BDS60"])
|
||||
mask = [IS10, IS17, IS20, IS30, IS40, IS44, IS45, IS50, IS60]
|
||||
else:
|
||||
allbds = np.array(["BDS10", "BDS17", "BDS20", "BDS30", "BDS40",
|
||||
"BDS50", "BDS60"])
|
||||
mask = [IS10, IS17, IS20, IS30, IS40, IS50, IS60]
|
||||
|
||||
bds = ','.join(sorted(allbds[mask]))
|
||||
|
||||
|
||||
@@ -14,13 +14,12 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
"""
|
||||
------------------------------------------
|
||||
BDS 0,5
|
||||
ADS-B TC=9-18
|
||||
Airborn position
|
||||
------------------------------------------
|
||||
"""
|
||||
# ------------------------------------------
|
||||
# BDS 0,5
|
||||
# ADS-B TC=9-18
|
||||
# Airborn position
|
||||
# ------------------------------------------
|
||||
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder import common
|
||||
|
||||
@@ -14,13 +14,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
"""
|
||||
------------------------------------------
|
||||
BDS 0,6
|
||||
ADS-B TC=5-8
|
||||
Surface position
|
||||
------------------------------------------
|
||||
"""
|
||||
# ------------------------------------------
|
||||
# BDS 0,6
|
||||
# ADS-B TC=5-8
|
||||
# Surface position
|
||||
# ------------------------------------------
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder import common
|
||||
@@ -143,15 +141,21 @@ def surface_position_with_ref(msg, lat_ref, lon_ref):
|
||||
return round(lat, 5), round(lon, 5)
|
||||
|
||||
|
||||
def surface_velocity(msg):
|
||||
def surface_velocity(msg, rtn_sources=False):
|
||||
"""Decode surface velocity from from a surface position message
|
||||
Args:
|
||||
msg (string): 28 bytes hexadecimal message string
|
||||
rtn_source (boolean): If the function will return
|
||||
the sources for direction of travel and vertical
|
||||
rate. This will change the return value from a four
|
||||
element array to a six element array.
|
||||
|
||||
Returns:
|
||||
(int, float, int, string): speed (kt), ground track (degree),
|
||||
rate of climb/descend (ft/min), and speed type
|
||||
('GS' for ground speed, 'AS' for airspeed)
|
||||
(int, float, int, string, string, None): speed (kt),
|
||||
ground track (degree), None for rate of climb/descend (ft/min),
|
||||
and speed type ('GS' for ground speed), direction source
|
||||
('true_north' for ground track / true north as reference),
|
||||
None rate of climb/descent source.
|
||||
"""
|
||||
|
||||
if common.typecode(msg) < 5 or common.typecode(msg) > 8:
|
||||
@@ -184,4 +188,7 @@ def surface_velocity(msg):
|
||||
spd = kts[i-1] + (mov-movs[i-1]) * step
|
||||
spd = round(spd, 2)
|
||||
|
||||
return spd, trk, 0, 'GS'
|
||||
if rtn_sources:
|
||||
return spd, trk, 0, 'GS', 'true_north', None
|
||||
else:
|
||||
return spd, trk, 0, 'GS'
|
||||
|
||||
@@ -14,13 +14,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
"""
|
||||
------------------------------------------
|
||||
BDS 0,8
|
||||
ADS-B TC=1-4
|
||||
Aircraft identitification and category
|
||||
------------------------------------------
|
||||
"""
|
||||
# ------------------------------------------
|
||||
# BDS 0,8
|
||||
# ADS-B TC=1-4
|
||||
# Aircraft identitification and category
|
||||
# ------------------------------------------
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder import common
|
||||
|
||||
@@ -14,29 +14,36 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
"""
|
||||
------------------------------------------
|
||||
BDS 0,9
|
||||
ADS-B TC=19
|
||||
Aircraft Airborn velocity
|
||||
------------------------------------------
|
||||
"""
|
||||
# ------------------------------------------
|
||||
# BDS 0,9
|
||||
# ADS-B TC=19
|
||||
# Aircraft Airborn velocity
|
||||
# ------------------------------------------
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder import common
|
||||
import math
|
||||
|
||||
|
||||
def airborne_velocity(msg):
|
||||
def airborne_velocity(msg, rtn_sources=False):
|
||||
"""Calculate the speed, track (or heading), and vertical rate
|
||||
|
||||
Args:
|
||||
msg (string): 28 bytes hexadecimal message string
|
||||
rtn_source (boolean): If the function will return
|
||||
the sources for direction of travel and vertical
|
||||
rate. This will change the return value from a four
|
||||
element array to a six element array.
|
||||
|
||||
Returns:
|
||||
(int, float, int, string): speed (kt), ground track or heading (degree),
|
||||
rate of climb/descend (ft/min), and speed type
|
||||
('GS' for ground speed, 'AS' for airspeed)
|
||||
(int, float, int, string, string, string): speed (kt),
|
||||
ground track or heading (degree),
|
||||
rate of climb/descent (ft/min), speed type
|
||||
('GS' for ground speed, 'AS' for airspeed),
|
||||
direction source ('true_north' for ground track / true north
|
||||
as refrence, 'mag_north' for magnetic north as reference),
|
||||
rate of climb/descent source ('Baro' for barometer, 'GNSS'
|
||||
for GNSS constellation).
|
||||
"""
|
||||
|
||||
if common.typecode(msg) != 19:
|
||||
@@ -52,9 +59,13 @@ def airborne_velocity(msg):
|
||||
if subtype in (1, 2):
|
||||
v_ew_sign = -1 if mb[13]=='1' else 1
|
||||
v_ew = common.bin2int(mb[14:24]) - 1 # east-west velocity
|
||||
if subtype == 2: # Supersonic
|
||||
v_ew *= 4
|
||||
|
||||
v_ns_sign = -1 if mb[24]=='1' else 1
|
||||
v_ns = common.bin2int(mb[25:35]) - 1 # north-south velocity
|
||||
if subtype == 2: # Supersonic
|
||||
v_ns *= 4
|
||||
|
||||
v_we = v_ew_sign * v_ew
|
||||
v_sn = v_ns_sign * v_ns
|
||||
@@ -68,6 +79,7 @@ def airborne_velocity(msg):
|
||||
|
||||
tag = 'GS'
|
||||
trk_or_hdg = round(trk, 2)
|
||||
dir_type = 'true_north'
|
||||
|
||||
else:
|
||||
if mb[13] == '0':
|
||||
@@ -80,17 +92,26 @@ def airborne_velocity(msg):
|
||||
|
||||
spd = common.bin2int(mb[25:35])
|
||||
spd = None if spd==0 else spd-1
|
||||
if subtype == 4: # Supersonic
|
||||
spd *= 4
|
||||
|
||||
if mb[24]=='0':
|
||||
tag = 'IAS'
|
||||
else:
|
||||
tag = 'TAS'
|
||||
|
||||
dir_type = 'mag_north'
|
||||
|
||||
vr_source = 'GNSS' if mb[35]=='0' else 'Baro'
|
||||
vr_sign = -1 if mb[36]=='1' else 1
|
||||
vr = common.bin2int(mb[37:46])
|
||||
rocd = None if vr==0 else int(vr_sign*(vr-1)*64)
|
||||
|
||||
return spd, trk_or_hdg, rocd, tag
|
||||
if rtn_sources:
|
||||
return spd, trk_or_hdg, rocd, tag, dir_type, vr_source
|
||||
else:
|
||||
return spd, trk_or_hdg, rocd, tag
|
||||
|
||||
|
||||
def altitude_diff(msg):
|
||||
"""Decode the differece between GNSS and barometric altitude
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
||||
|
||||
# ------------------------------------------
|
||||
# BDS 1,0
|
||||
# Data link capability report
|
||||
# ------------------------------------------
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
||||
|
||||
def is10(msg):
|
||||
"""Check if a message is likely to be BDS code 1,0
|
||||
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# ------------------------------------------
|
||||
# BDS 1,7
|
||||
# Common usage GICB capability report
|
||||
# ------------------------------------------
|
||||
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
||||
|
||||
"""
|
||||
------------------------------------------
|
||||
BDS 1,7
|
||||
Common usage GICB capability report
|
||||
------------------------------------------
|
||||
"""
|
||||
|
||||
def is17(msg):
|
||||
"""Check if a message is likely to be BDS code 1,7
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
||||
|
||||
# ------------------------------------------
|
||||
# BDS 2,0
|
||||
# Aircraft identification
|
||||
# ------------------------------------------
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
||||
|
||||
def is20(msg):
|
||||
"""Check if a message is likely to be BDS code 2,0
|
||||
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
||||
|
||||
# ------------------------------------------
|
||||
# BDS 3,0
|
||||
# ACAS active resolution advisory
|
||||
# ------------------------------------------
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros
|
||||
|
||||
def is30(msg):
|
||||
"""Check if a message is likely to be BDS code 2,0
|
||||
|
||||
|
||||
@@ -13,15 +13,16 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||
|
||||
# ------------------------------------------
|
||||
# BDS 4,0
|
||||
# Selected vertical intention
|
||||
# ------------------------------------------
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
import warnings
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||
|
||||
|
||||
def is40(msg):
|
||||
"""Check if a message is likely to be BDS code 4,0
|
||||
|
||||
@@ -47,10 +48,10 @@ def is40(msg):
|
||||
|
||||
if wrongstatus(d, 27, 28, 39):
|
||||
return False
|
||||
|
||||
|
||||
if wrongstatus(d, 48, 49, 51):
|
||||
return False
|
||||
|
||||
|
||||
if wrongstatus(d, 54, 55, 56):
|
||||
return False
|
||||
|
||||
@@ -65,7 +66,7 @@ def is40(msg):
|
||||
return True
|
||||
|
||||
|
||||
def alt40mcp(msg):
|
||||
def selalt40mcp(msg):
|
||||
"""Selected altitude, MCP/FCU
|
||||
|
||||
Args:
|
||||
@@ -76,14 +77,14 @@ def alt40mcp(msg):
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
if d[0] == '0':
|
||||
if d[0] == "0":
|
||||
return None
|
||||
|
||||
alt = bin2int(d[1:13]) * 16 # ft
|
||||
alt = bin2int(d[1:13]) * 16 # ft
|
||||
return alt
|
||||
|
||||
|
||||
def alt40fms(msg):
|
||||
def selalt40fms(msg):
|
||||
"""Selected altitude, FMS
|
||||
|
||||
Args:
|
||||
@@ -94,10 +95,10 @@ def alt40fms(msg):
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
if d[13] == '0':
|
||||
if d[13] == "0":
|
||||
return None
|
||||
|
||||
alt = bin2int(d[14:26]) * 16 # ft
|
||||
alt = bin2int(d[14:26]) * 16 # ft
|
||||
return alt
|
||||
|
||||
|
||||
@@ -112,8 +113,26 @@ def p40baro(msg):
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
if d[26] == '0':
|
||||
if d[26] == "0":
|
||||
return None
|
||||
|
||||
p = bin2int(d[27:39]) * 0.1 + 800 # millibar
|
||||
p = bin2int(d[27:39]) * 0.1 + 800 # millibar
|
||||
return p
|
||||
|
||||
|
||||
def alt40mcp(msg):
|
||||
warnings.simplefilter("once", DeprecationWarning)
|
||||
warnings.warn(
|
||||
"alt40mcp() has been renamed to selalt40mcp(). It will be removed in the future.",
|
||||
DeprecationWarning,
|
||||
)
|
||||
return selalt40mcp(msg)
|
||||
|
||||
|
||||
def alt40fms(msg):
|
||||
warnings.simplefilter("once", DeprecationWarning)
|
||||
warnings.warn(
|
||||
"alt40fms() has been renamed to selalt40fms(). It will be removed in the future.",
|
||||
DeprecationWarning,
|
||||
)
|
||||
return selalt40mcp(msg)
|
||||
|
||||
@@ -13,206 +13,171 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||
|
||||
# ------------------------------------------
|
||||
# BDS 4,4
|
||||
# Meteorological routine air report
|
||||
# ------------------------------------------
|
||||
|
||||
def is44(msg, rev=False):
|
||||
"""Check if a message is likely to be BDS code 4,4
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import (
|
||||
hex2bin,
|
||||
bin2int,
|
||||
data,
|
||||
allzeros,
|
||||
wrongstatus,
|
||||
)
|
||||
|
||||
|
||||
def is44(msg):
|
||||
"""Check if a message is likely to be BDS code 4,4.
|
||||
|
||||
Meteorological routine air report
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
rev (bool): using revised version
|
||||
|
||||
Returns:
|
||||
bool: True or False
|
||||
"""
|
||||
|
||||
"""
|
||||
if allzeros(msg):
|
||||
return False
|
||||
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
|
||||
if not rev:
|
||||
# status bit 5, 35, 47, 50
|
||||
if wrongstatus(d, 5, 6, 23):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 35, 36, 46):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 47, 48, 49):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 50, 51, 56):
|
||||
return False
|
||||
|
||||
# Bits 1-4 indicate source, values > 4 reserved and should not occur
|
||||
if bin2int(d[0:4]) > 4:
|
||||
return False
|
||||
else:
|
||||
# status bit 5, 15, 24, 36, 49
|
||||
if wrongstatus(d, 5, 6, 14):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 15, 16, 23):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 24, 25, 35):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 36, 37, 47):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 49, 50, 56):
|
||||
return False
|
||||
|
||||
# Bits 1-4 are reserved and should be zero
|
||||
if bin2int(d[0:4]) != 0:
|
||||
return False
|
||||
|
||||
vw = wind44(msg, rev=rev)
|
||||
if vw is not None and vw[0] > 250:
|
||||
# status bit 5, 35, 47, 50
|
||||
if wrongstatus(d, 5, 6, 23):
|
||||
return False
|
||||
|
||||
if temp44(msg):
|
||||
if temp44(msg) > 60 or temp44(msg) < -80:
|
||||
return False
|
||||
if wrongstatus(d, 35, 36, 46):
|
||||
return False
|
||||
|
||||
elif temp44(msg) == 0:
|
||||
if wrongstatus(d, 47, 48, 49):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 50, 51, 56):
|
||||
return False
|
||||
|
||||
# Bits 1-4 indicate source, values > 4 reserved and should not occur
|
||||
if bin2int(d[0:4]) > 4:
|
||||
return False
|
||||
|
||||
vw, dw = wind44(msg)
|
||||
if vw is not None and vw > 250:
|
||||
return False
|
||||
|
||||
temp, temp2 = temp44(msg)
|
||||
if min(temp, temp2) > 60 or max(temp, temp2) < -80:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def wind44(msg, rev=False):
|
||||
"""reported wind speed and direction
|
||||
def wind44(msg):
|
||||
"""Wind speed and direction.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message (BDS44) string
|
||||
rev (bool): using revised version
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
(int, float): speed (kt), direction (degree)
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
if not rev:
|
||||
status = int(d[4])
|
||||
if not status:
|
||||
return None
|
||||
status = int(d[4])
|
||||
if not status:
|
||||
return None, None
|
||||
|
||||
speed = bin2int(d[5:14]) # knots
|
||||
direction = bin2int(d[14:23]) * 180.0 / 256.0 # degree
|
||||
|
||||
else:
|
||||
spd_status = int(d[4])
|
||||
dir_status = int(d[14])
|
||||
|
||||
if (not spd_status) or (not dir_status):
|
||||
return None
|
||||
|
||||
speed = bin2int(d[5:14]) # knots
|
||||
direction = bin2int(d[15:23]) * 180.0 / 128.0 # degree
|
||||
speed = bin2int(d[5:14]) # knots
|
||||
direction = bin2int(d[14:23]) * 180.0 / 256.0 # degree
|
||||
|
||||
return round(speed, 0), round(direction, 1)
|
||||
|
||||
|
||||
def temp44(msg, rev=False):
|
||||
"""reported air temperature
|
||||
def temp44(msg):
|
||||
"""Static air temperature.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message (BDS44) string
|
||||
rev (bool): using revised version
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
float: tmeperature in Celsius degree
|
||||
float, float: temperature and alternative temperature in Celsius degree.
|
||||
Note: Two values returns due to what seems to be an inconsistancy
|
||||
error in ICAO 9871 (2008) Appendix A-67.
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
if not rev:
|
||||
# if d[22] == '0':
|
||||
# return None
|
||||
sign = int(d[23])
|
||||
value = bin2int(d[24:34])
|
||||
|
||||
sign = int(d[23])
|
||||
value = bin2int(d[24:34])
|
||||
if sign:
|
||||
value = value - 1024
|
||||
|
||||
if sign:
|
||||
value = value - 1024
|
||||
temp = value * 0.25 # celsius
|
||||
temp = round(temp, 2)
|
||||
|
||||
temp = value * 0.125 # celsius
|
||||
temp = round(temp, 1)
|
||||
else:
|
||||
# if d[23] == '0':
|
||||
# return None
|
||||
temp_alternative = value * 0.125 # celsius
|
||||
temp_alternative = round(temp_alternative, 3)
|
||||
|
||||
sign = int(d[24])
|
||||
value = bin2int(d[25:35])
|
||||
|
||||
if sign:
|
||||
value = value - 1024
|
||||
|
||||
temp = value * 0.125 # celsius
|
||||
temp = round(temp, 1)
|
||||
|
||||
return temp
|
||||
return temp, temp_alternative
|
||||
|
||||
|
||||
def p44(msg, rev=False):
|
||||
"""reported average static pressure
|
||||
def p44(msg):
|
||||
"""Static pressure.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message (BDS44) string
|
||||
rev (bool): using revised version
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
int: static pressure in hPa
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
if not rev:
|
||||
if d[34] == '0':
|
||||
return None
|
||||
if d[34] == "0":
|
||||
return None
|
||||
|
||||
p = bin2int(d[35:46]) # hPa
|
||||
|
||||
else:
|
||||
if d[35] == '0':
|
||||
return None
|
||||
|
||||
p = bin2int(d[36:47]) # hPa
|
||||
p = bin2int(d[35:46]) # hPa
|
||||
|
||||
return p
|
||||
|
||||
|
||||
def hum44(msg, rev=False):
|
||||
"""reported humidity
|
||||
def hum44(msg):
|
||||
"""humidity
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message (BDS44) string
|
||||
rev (bool): using revised version
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
float: percentage of humidity, [0 - 100] %
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
if not rev:
|
||||
if d[49] == '0':
|
||||
return None
|
||||
if d[49] == "0":
|
||||
return None
|
||||
|
||||
hm = bin2int(d[50:56]) * 100.0 / 64 # %
|
||||
|
||||
else:
|
||||
if d[48] == '0':
|
||||
return None
|
||||
|
||||
hm = bin2int(d[49:56]) # %
|
||||
hm = bin2int(d[50:56]) * 100.0 / 64 # %
|
||||
|
||||
return round(hm, 1)
|
||||
|
||||
|
||||
def turb44(msg):
|
||||
"""Turblence.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
int: turbulence level. 0=NIL, 1=Light, 2=Moderate, 3=Severe
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
if d[46] == "0":
|
||||
return None
|
||||
|
||||
turb = bin2int(d[47:49])
|
||||
|
||||
return turb
|
||||
|
||||
224
pyModeS/decoder/bds/bds45.py
Normal file
224
pyModeS/decoder/bds/bds45.py
Normal file
@@ -0,0 +1,224 @@
|
||||
# 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/>.
|
||||
|
||||
# ------------------------------------------
|
||||
# BDS 4,5
|
||||
# Meteorological hazard report
|
||||
# ------------------------------------------
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||
|
||||
|
||||
def is45(msg):
|
||||
"""Check if a message is likely to be BDS code 4,5.
|
||||
|
||||
Meteorological hazard report
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
bool: True or False
|
||||
|
||||
"""
|
||||
if allzeros(msg):
|
||||
return False
|
||||
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
# status bit 1, 4, 7, 10, 13, 16, 27, 39
|
||||
if wrongstatus(d, 1, 2, 3):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 4, 5, 6):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 7, 8, 9):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 10, 11, 12):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 13, 14, 15):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 16, 17, 26):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 27, 28, 38):
|
||||
return False
|
||||
|
||||
if wrongstatus(d, 39, 40, 51):
|
||||
return False
|
||||
|
||||
# reserved
|
||||
if bin2int(d[51:56]) != 0:
|
||||
return False
|
||||
|
||||
temp = temp45(msg)
|
||||
if temp:
|
||||
if temp > 60 or temp < -80:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def turb45(msg):
|
||||
"""Turbulence.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
int: Turbulence level. 0=NIL, 1=Light, 2=Moderate, 3=Severe
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
if d[0] == '0':
|
||||
return None
|
||||
|
||||
turb = bin2int(d[1:3])
|
||||
return turb
|
||||
|
||||
|
||||
def ws45(msg):
|
||||
"""Wind shear.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
int: Wind shear level. 0=NIL, 1=Light, 2=Moderate, 3=Severe
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
if d[3] == '0':
|
||||
return None
|
||||
|
||||
ws = bin2int(d[4:6])
|
||||
return ws
|
||||
|
||||
|
||||
def mb45(msg):
|
||||
"""Microburst.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
int: Microburst level. 0=NIL, 1=Light, 2=Moderate, 3=Severe
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
if d[6] == '0':
|
||||
return None
|
||||
|
||||
mb = bin2int(d[7:9])
|
||||
return mb
|
||||
|
||||
|
||||
def ic45(msg):
|
||||
"""Icing.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
int: Icing level. 0=NIL, 1=Light, 2=Moderate, 3=Severe
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
if d[9] == '0':
|
||||
return None
|
||||
|
||||
ic = bin2int(d[10:12])
|
||||
return ic
|
||||
|
||||
|
||||
def wv45(msg):
|
||||
"""Wake vortex.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
int: Wake vortex level. 0=NIL, 1=Light, 2=Moderate, 3=Severe
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
if d[12] == '0':
|
||||
return None
|
||||
|
||||
ws = bin2int(d[13:15])
|
||||
return ws
|
||||
|
||||
|
||||
def temp45(msg):
|
||||
"""Static air temperature.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
float: tmeperature in Celsius degree
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
sign = int(d[16])
|
||||
value = bin2int(d[17:26])
|
||||
|
||||
if sign:
|
||||
value = value - 512
|
||||
|
||||
temp = value * 0.25 # celsius
|
||||
temp = round(temp, 1)
|
||||
|
||||
return temp
|
||||
|
||||
|
||||
def p45(msg):
|
||||
"""Average static pressure.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
int: static pressure in hPa
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
if d[26] == '0':
|
||||
return None
|
||||
p = bin2int(d[27:38]) # hPa
|
||||
return p
|
||||
|
||||
|
||||
def rh45(msg):
|
||||
"""Radio height.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
int: radio height in ft
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
if d[38] == '0':
|
||||
return None
|
||||
rh = bin2int(d[39:51]) * 16
|
||||
return rh
|
||||
@@ -13,14 +13,15 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||
|
||||
# ------------------------------------------
|
||||
# BDS 5,0
|
||||
# Track and turn report
|
||||
# ------------------------------------------
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||
|
||||
|
||||
def is50(msg):
|
||||
"""Check if a message is likely to be BDS code 5,0
|
||||
(Track and turn report)
|
||||
|
||||
@@ -13,14 +13,15 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||
|
||||
# ------------------------------------------
|
||||
# BDS 5,3
|
||||
# Air-referenced state vector
|
||||
# ------------------------------------------
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||
|
||||
|
||||
def is53(msg):
|
||||
"""Check if a message is likely to be BDS code 5,3
|
||||
(Air-referenced state vector)
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||
|
||||
# ------------------------------------------
|
||||
# BDS 6,0
|
||||
# Heading and speed report
|
||||
# ------------------------------------------
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
from pyModeS.decoder.common import hex2bin, bin2int, data, allzeros, wrongstatus
|
||||
|
||||
def is60(msg):
|
||||
"""Check if a message is likely to be BDS code 6,0
|
||||
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
"""Comm-B Wrapper.
|
||||
|
||||
The Comm-B wrapper imports all functions from the following modules:
|
||||
|
||||
**ELS - elementary surveillance**
|
||||
- pyModeS.decoder.bds.bds10
|
||||
- pyModeS.decoder.bds.bds17
|
||||
- pyModeS.decoder.bds.bds20
|
||||
- pyModeS.decoder.bds.bds30
|
||||
|
||||
**EHS - enhanced surveillance**
|
||||
- pyModeS.decoder.bds.bds40
|
||||
- pyModeS.decoder.bds.bds50
|
||||
- pyModeS.decoder.bds.bds60
|
||||
|
||||
**MRAR and MHR**
|
||||
- pyModeS.decoder.bds.bds44
|
||||
- pyModeS.decoder.bds.bds45
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
|
||||
# ELS - elementary surveillance
|
||||
@@ -11,5 +32,6 @@ from pyModeS.decoder.bds.bds40 import *
|
||||
from pyModeS.decoder.bds.bds50 import *
|
||||
from pyModeS.decoder.bds.bds60 import *
|
||||
|
||||
# MRAR
|
||||
# MRAR and MHR
|
||||
from pyModeS.decoder.bds.bds44 import *
|
||||
from pyModeS.decoder.bds.bds45 import *
|
||||
|
||||
@@ -1,49 +1,94 @@
|
||||
from __future__ import absolute_import, print_function, division
|
||||
import numpy as np
|
||||
from textwrap import wrap
|
||||
|
||||
def hex2bin(hexstr):
|
||||
"""Convert a hexdecimal string to binary string, with zero fillings. """
|
||||
"""Convert a hexdecimal string to binary string, with zero fillings."""
|
||||
num_of_bits = len(hexstr) * 4
|
||||
binstr = bin(int(hexstr, 16))[2:].zfill(int(num_of_bits))
|
||||
return binstr
|
||||
|
||||
|
||||
def bin2int(binstr):
|
||||
"""Convert a binary string to integer. """
|
||||
return int(binstr, 2)
|
||||
|
||||
|
||||
def hex2int(hexstr):
|
||||
"""Convert a hexdecimal string to integer. """
|
||||
"""Convert a hexdecimal string to integer."""
|
||||
return int(hexstr, 16)
|
||||
|
||||
|
||||
def int2hex(n):
|
||||
"""Convert a integer to hexadecimal string."""
|
||||
return hex(n)[2:].rjust(6, '0').upper()
|
||||
|
||||
|
||||
def bin2int(binstr):
|
||||
"""Convert a binary string to integer."""
|
||||
return int(binstr, 2)
|
||||
|
||||
|
||||
def bin2hex(hexstr):
|
||||
"""Convert a hexdecimal string to integer."""
|
||||
return int2hex(bin2int(hexstr))
|
||||
|
||||
|
||||
def bin2np(binstr):
|
||||
"""Convert a binary string to numpy array. """
|
||||
"""Convert a binary string to numpy array."""
|
||||
return np.array([int(i) for i in binstr])
|
||||
|
||||
|
||||
def np2bin(npbin):
|
||||
"""Convert a binary numpy array to string. """
|
||||
"""Convert a binary numpy array to string."""
|
||||
return np.array2string(npbin, separator='')[1:-1]
|
||||
|
||||
|
||||
def df(msg):
|
||||
"""Decode Downlink Format vaule, bits 1 to 5."""
|
||||
msgbin = hex2bin(msg)
|
||||
return min( bin2int(msgbin[0:5]) , 24 )
|
||||
return min(bin2int(msgbin[0:5]), 24)
|
||||
|
||||
|
||||
def crc(msg, encode=False):
|
||||
"""Mode-S Cyclic Redundancy Check
|
||||
Detect if bit error occurs in the Mode-S message
|
||||
"""Mode-S Cyclic Redundancy Check.
|
||||
|
||||
Detect if bit error occurs in the Mode-S message. When encode option is on,
|
||||
the checksum is generated.
|
||||
|
||||
Args:
|
||||
msg (string): 28 bytes hexadecimal message string
|
||||
encode (bool): True to encode the date only and return the checksum
|
||||
Returns:
|
||||
string: message checksum, or partity bits (encoder)
|
||||
"""
|
||||
int: message checksum, or partity bits (encoder)
|
||||
|
||||
"""
|
||||
# the CRC generator
|
||||
G = [
|
||||
int("11111111", 2), int("11111010", 2),
|
||||
int("00000100", 2), int("10000000", 2)
|
||||
]
|
||||
|
||||
if encode:
|
||||
msg = msg[:-6] + "000000"
|
||||
|
||||
msgbin = hex2bin(msg)
|
||||
msgbin_split = wrap(msgbin, 8)
|
||||
mbytes = list(map(bin2int, msgbin_split))
|
||||
|
||||
for ibyte in range(len(mbytes)-3):
|
||||
for ibit in range(8):
|
||||
mask = 0x80 >> ibit
|
||||
bits = mbytes[ibyte] & mask
|
||||
|
||||
if bits > 0:
|
||||
mbytes[ibyte] = mbytes[ibyte] ^ (G[0] >> ibit)
|
||||
mbytes[ibyte+1] = mbytes[ibyte+1] ^ (0xFF & ((G[0] << 8-ibit) | (G[1] >> ibit)))
|
||||
mbytes[ibyte+2] = mbytes[ibyte+2] ^ (0xFF & ((G[1] << 8-ibit) | (G[2] >> ibit)))
|
||||
mbytes[ibyte+3] = mbytes[ibyte+3] ^ (0xFF & ((G[2] << 8-ibit) | (G[3] >> ibit)))
|
||||
|
||||
result = (mbytes[-3] << 16) | (mbytes[-2] << 8) | mbytes[-1]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def crc_legacy(msg, encode=False):
|
||||
"""Mode-S Cyclic Redundancy Check. (Legacy code, 2x slow)."""
|
||||
# the polynominal generattor code for CRC [1111111111111010000001001]
|
||||
generator = np.array([1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,1,0,0,1])
|
||||
ng = len(generator)
|
||||
@@ -62,37 +107,38 @@ def crc(msg, encode=False):
|
||||
msgnpbin[i:i+ng] = np.bitwise_xor(msgnpbin[i:i+ng], generator)
|
||||
|
||||
# last 24 bits
|
||||
reminder = np2bin(msgnpbin[-24:])
|
||||
reminder = bin2int(np2bin(msgnpbin[-24:]))
|
||||
return reminder
|
||||
|
||||
|
||||
def floor(x):
|
||||
""" Mode-S floor function
|
||||
"""Mode-S floor function.
|
||||
|
||||
Defined as the greatest integer value k, such that k <= x
|
||||
Defined as the greatest integer value k, such that k <= x
|
||||
For example: floor(3.6) = 3 and floor(-3.6) = -4
|
||||
|
||||
eg.: floor(3.6) = 3, while floor(-3.6) = -4
|
||||
"""
|
||||
return int(np.floor(x))
|
||||
|
||||
|
||||
def icao(msg):
|
||||
"""Calculate the ICAO address from an Mode-S message
|
||||
with DF4, DF5, DF20, DF21
|
||||
"""Calculate the ICAO address from an Mode-S message.
|
||||
|
||||
Applicable only with DF4, DF5, DF20, DF21 messages.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
String: ICAO address in 6 bytes hexadecimal string
|
||||
"""
|
||||
|
||||
"""
|
||||
DF = df(msg)
|
||||
|
||||
if DF in (11, 17, 18):
|
||||
addr = msg[2:8]
|
||||
elif DF in (0, 4, 5, 16, 20, 21):
|
||||
c0 = bin2int(crc(msg, encode=True))
|
||||
c0 = crc(msg, encode=True)
|
||||
c1 = hex2int(msg[-6:])
|
||||
addr = '%06X' % (c0 ^ c1)
|
||||
else:
|
||||
@@ -102,8 +148,7 @@ def icao(msg):
|
||||
|
||||
|
||||
def is_icao_assigned(icao):
|
||||
""" Check whether the ICAO address is assigned (Annex 10, Vol 3)"""
|
||||
|
||||
"""Check whether the ICAO address is assigned (Annex 10, Vol 3)."""
|
||||
if (icao is None) or (not isinstance(icao, str)) or (len(icao)!=6):
|
||||
return False
|
||||
|
||||
@@ -138,7 +183,7 @@ def typecode(msg):
|
||||
|
||||
|
||||
def cprNL(lat):
|
||||
"""NL() function in CPR decoding"""
|
||||
"""NL() function in CPR decoding."""
|
||||
|
||||
if lat == 0:
|
||||
return 59
|
||||
@@ -156,8 +201,11 @@ def cprNL(lat):
|
||||
NL = floor(nl)
|
||||
return NL
|
||||
|
||||
|
||||
def idcode(msg):
|
||||
"""Computes identity (squawk code) from DF5 or DF21 message, bit 20-32.
|
||||
"""Compute identity (squawk code).
|
||||
|
||||
Applicable only for DF5 or DF21 messages, bit 20-32.
|
||||
credit: @fbyrkjeland
|
||||
|
||||
Args:
|
||||
@@ -165,8 +213,8 @@ def idcode(msg):
|
||||
|
||||
Returns:
|
||||
string: squawk code
|
||||
"""
|
||||
|
||||
"""
|
||||
if df(msg) not in [5, 21]:
|
||||
raise RuntimeError("Message must be Downlink Format 5 or 21.")
|
||||
|
||||
@@ -195,7 +243,9 @@ def idcode(msg):
|
||||
|
||||
|
||||
def altcode(msg):
|
||||
"""Computes the altitude from DF4 or DF20 message, bit 20-32.
|
||||
"""Compute the altitude.
|
||||
|
||||
Applicable only for DF4 or DF20 message, bit 20-32.
|
||||
credit: @fbyrkjeland
|
||||
|
||||
Args:
|
||||
@@ -203,8 +253,8 @@ def altcode(msg):
|
||||
|
||||
Returns:
|
||||
int: altitude in ft
|
||||
"""
|
||||
|
||||
"""
|
||||
if df(msg) not in [0, 4, 16, 20]:
|
||||
raise RuntimeError("Message must be Downlink Format 0, 4, 16, or 20.")
|
||||
|
||||
@@ -266,7 +316,7 @@ def gray2alt(codestr):
|
||||
|
||||
|
||||
def gray2int(graystr):
|
||||
"""Convert greycode to binary"""
|
||||
"""Convert greycode to binary."""
|
||||
num = bin2int(graystr)
|
||||
num ^= (num >> 8)
|
||||
num ^= (num >> 4)
|
||||
@@ -276,18 +326,19 @@ def gray2int(graystr):
|
||||
|
||||
|
||||
def data(msg):
|
||||
"""Return the data frame in the message, bytes 9 to 22"""
|
||||
"""Return the data frame in the message, bytes 9 to 22."""
|
||||
return msg[8:-6]
|
||||
|
||||
|
||||
def allzeros(msg):
|
||||
"""check if the data bits are all zeros
|
||||
"""Check if the data bits are all zeros.
|
||||
|
||||
Args:
|
||||
msg (String): 28 bytes hexadecimal message string
|
||||
|
||||
Returns:
|
||||
bool: True or False
|
||||
|
||||
"""
|
||||
d = hex2bin(data(msg))
|
||||
|
||||
@@ -298,10 +349,11 @@ def allzeros(msg):
|
||||
|
||||
|
||||
def wrongstatus(data, sb, msb, lsb):
|
||||
"""Check if the status bit and field bits are consistency. This Function
|
||||
is used for checking BDS code versions.
|
||||
"""
|
||||
"""Check if the status bit and field bits are consistency.
|
||||
|
||||
This Function is used for checking BDS code versions.
|
||||
|
||||
"""
|
||||
# status bit, most significant bit, least significant bit
|
||||
status = int(data[sb-1])
|
||||
value = bin2int(data[msb-1:lsb])
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
"""EHS Wrapper.
|
||||
|
||||
``pyModeS.ehs`` is deprecated, please use ``pyModeS.commb`` instead.
|
||||
|
||||
The EHS wrapper imports all functions from the following modules:
|
||||
- pyModeS.decoder.bds.bds40
|
||||
- pyModeS.decoder.bds.bds50
|
||||
- pyModeS.decoder.bds.bds60
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
import warnings
|
||||
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
"""ELS Wrapper.
|
||||
|
||||
``pyModeS.els`` is deprecated, please use ``pyModeS.commb`` instead.
|
||||
|
||||
The ELS wrapper imports all functions from the following modules:
|
||||
- pyModeS.decoder.bds.bds10
|
||||
- pyModeS.decoder.bds.bds17
|
||||
- pyModeS.decoder.bds.bds20
|
||||
- pyModeS.decoder.bds.bds30
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
|
||||
from pyModeS.decoder.bds.bds10 import *
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
"""
|
||||
Warpper for short roll call surveillance replies DF=4/5
|
||||
|
||||
[To be implemented]
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, print_function, division
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
"""Uncertainty parameters.
|
||||
|
||||
See source code at: https://github.com/junzis/pyModeS/blob/master/pyModeS/decoder/uncertainty.py
|
||||
"""
|
||||
|
||||
NA = None
|
||||
|
||||
TC_NUCp_lookup = {
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
"""
|
||||
Functions for aeronautics in this module
|
||||
- physical quantities always in SI units
|
||||
- lat,lon,course and heading in degrees
|
||||
|
||||
- physical quantities always in SI units
|
||||
- lat,lon,course and heading in degrees
|
||||
|
||||
International Standard Atmosphere
|
||||
::
|
||||
|
||||
p,rho,T = atmos(H) # atmos as function of geopotential altitude H [m]
|
||||
a = vsound(H) # speed of sound [m/s] as function of H[m]
|
||||
p = pressure(H) # calls atmos but retruns only pressure [Pa]
|
||||
T = temperature(H) # calculates temperature [K]
|
||||
rho = density(H) # calls atmos but retruns only pressure [Pa]
|
||||
|
||||
Speed conversion at altitude H[m] in ISA:
|
||||
Speed conversion at altitude H[m] in ISA
|
||||
::
|
||||
|
||||
Mach = tas2mach(Vtas,H) # true airspeed (Vtas) to mach number conversion
|
||||
Vtas = mach2tas(Mach,H) # true airspeed (Vtas) to mach number conversion
|
||||
Vtas = eas2tas(Veas,H) # equivalent airspeed to true airspeed, H in [m]
|
||||
@@ -19,6 +24,7 @@ Speed conversion at altitude H[m] in ISA:
|
||||
Vcas = tas2cas(Vtas,H) # Vtas to Vcas conversion both m/s, H in [m]
|
||||
Vcas = mach2cas(Mach,H) # Mach to Vcas conversion Vcas in m/s, H in [m]
|
||||
Mach = cas2mach(Vcas,H) # Vcas to mach copnversion Vcas in m/s, H in [m]
|
||||
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
|
||||
@@ -6,7 +6,9 @@ import os
|
||||
import sys
|
||||
import socket
|
||||
import time
|
||||
import pyModeS as pms
|
||||
from threading import Thread
|
||||
import traceback
|
||||
|
||||
if (sys.version_info > (3, 0)):
|
||||
PY_VERSION = 3
|
||||
@@ -137,59 +139,72 @@ class BaseClient(Thread):
|
||||
# Other message tupe
|
||||
continue
|
||||
|
||||
if len(msg) not in [14, 28]:
|
||||
# incomplete message
|
||||
df = pms.df(msg)
|
||||
|
||||
# skip incomplete message
|
||||
if df in [0, 4, 5, 11] and len(msg) != 14:
|
||||
continue
|
||||
if df in [16, 17, 18, 19, 20, 21, 24] and len(msg) != 28:
|
||||
continue
|
||||
|
||||
messages.append([msg, ts])
|
||||
return messages
|
||||
|
||||
def read_skysense_buffer(self):
|
||||
"""
|
||||
----------------------------------------------------------------------------------
|
||||
Field SS MS MS MS MS MS MS MS MS MS MS MS MS MS MS TS TS TS TS TS TS RS RS RS
|
||||
----------------------------------------------------------------------------------
|
||||
Position: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
SS field - Start character
|
||||
Position 0:
|
||||
1 byte = 8 bits
|
||||
Start character '$'
|
||||
|
||||
MS field - Payload
|
||||
Postion 1 through 14:
|
||||
14 bytes = 112 bits
|
||||
Mode-S payload
|
||||
In case of DF types that only carry 7 bytes of information position 8 through 14 are set to 0x00.
|
||||
|
||||
TS field - Time stamp
|
||||
Position 15 through 20:
|
||||
6 bytes = 48 bits
|
||||
Time stamp with fields as:
|
||||
|
||||
Lock Status - Status of internal time keeping mechanism
|
||||
Equal to 1 if operating normally
|
||||
Bit 47 - 1 bit
|
||||
|
||||
Time of day in UTC seconds, between 0 and 86399
|
||||
Bits 46 through 30 - 17 bits
|
||||
|
||||
Nanoseconds into current second, between 0 and 999999999
|
||||
Bits 29 through 0 - 30 bits
|
||||
|
||||
RS field - Signal Level
|
||||
Position 21 through 23:
|
||||
3 bytes = 24 bits
|
||||
RSSI (received signal strength indication) and relative noise level with fields
|
||||
|
||||
RNL, Q12.4 unsigned fixed point binary with 4 fractional bits and 8 integer bits.
|
||||
This is and indication of the noise level of the message. Roughly 40 counts per 10dBm.
|
||||
Bits 23 through 12 - 12 bits
|
||||
|
||||
RSSI, Q12.4 unsigned fixed point binary with 4 fractional bits and 8 integer bits.
|
||||
This is an indication of the signal level of the received message in ADC counts. Roughly 40 counts per 10dBm.
|
||||
Bits 11 through 0 - 12 bits
|
||||
"""Skysense stream format.
|
||||
|
||||
::
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
Field SS MS MS MS MS MS MS MS MS MS MS MS MS MS MS TS TS TS TS TS TS RS RS RS
|
||||
----------------------------------------------------------------------------------
|
||||
Position: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
SS field - Start character
|
||||
Position 0:
|
||||
1 byte = 8 bits
|
||||
Start character '$'
|
||||
|
||||
MS field - Payload
|
||||
Postion 1 through 14:
|
||||
14 bytes = 112 bits
|
||||
Mode-S payload
|
||||
In case of DF types that only carry 7 bytes of information
|
||||
position 8 through 14 are set to 0x00.
|
||||
|
||||
TS field - Time stamp
|
||||
Position 15 through 20:
|
||||
6 bytes = 48 bits
|
||||
Time stamp with fields as:
|
||||
|
||||
Lock Status - Status of internal time keeping mechanism
|
||||
Equal to 1 if operating normally
|
||||
Bit 47 - 1 bit
|
||||
|
||||
Time of day in UTC seconds, between 0 and 86399
|
||||
Bits 46 through 30 - 17 bits
|
||||
|
||||
Nanoseconds into current second, between 0 and 999999999
|
||||
Bits 29 through 0 - 30 bits
|
||||
|
||||
RS field - Signal Level
|
||||
Position 21 through 23:
|
||||
3 bytes = 24 bits
|
||||
RSSI (received signal strength indication) and relative
|
||||
noise level with fields
|
||||
|
||||
RNL, Q12.4 unsigned fixed point binary with 4 fractional
|
||||
bits and 8 integer bits.
|
||||
This is and indication of the noise level of the message.
|
||||
Roughly 40 counts per 10dBm.
|
||||
Bits 23 through 12 - 12 bits
|
||||
|
||||
RSSI, Q12.4 unsigned fixed point binary with 4 fractional
|
||||
bits and 8 integer bits.
|
||||
This is an indication of the signal level of the received
|
||||
message in ADC counts. Roughly 40 counts per 10dBm.
|
||||
Bits 11 through 0 - 12 bits
|
||||
"""
|
||||
SS_MSGLENGTH = 24
|
||||
SS_STARTCHAR = 0x24
|
||||
@@ -220,7 +235,7 @@ class BaseClient(Thread):
|
||||
self.buffer = self.buffer[SS_MSGLENGTH:]
|
||||
messages.append( [msg,ts] )
|
||||
else:
|
||||
self.buffer = self.buffer[1:]
|
||||
self.buffer = self.buffer[1:]
|
||||
return messages
|
||||
|
||||
def handle_messages(self, messages):
|
||||
@@ -260,7 +275,16 @@ class BaseClient(Thread):
|
||||
|
||||
time.sleep(0.001)
|
||||
except Exception as e:
|
||||
print("Unexpected Error:", e)
|
||||
|
||||
# Provides the user an option to supply the environment
|
||||
# variable PYMODES_DEBUG to halt the execution
|
||||
# for debugging purposes
|
||||
debug_intent = os.environ.get('PYMODES_DEBUG', 'false')
|
||||
if debug_intent.lower() == 'true':
|
||||
traceback.print_exc()
|
||||
sys.exit()
|
||||
else:
|
||||
print("Unexpected Error:", e)
|
||||
|
||||
try:
|
||||
sock = self.connect()
|
||||
|
||||
65
setup.py
65
setup.py
@@ -14,6 +14,7 @@ Steps for deploying a new verison:
|
||||
|
||||
# Always prefer setuptools over distutils
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
# To use a consistent encoding
|
||||
from codecs import open
|
||||
from os import path
|
||||
@@ -21,73 +22,59 @@ from os import path
|
||||
here = path.abspath(path.dirname(__file__))
|
||||
|
||||
# Get the long description from the README file
|
||||
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
|
||||
with open(path.join(here, "README.rst"), encoding="utf-8") as f:
|
||||
long_description = f.read()
|
||||
|
||||
setup(
|
||||
name='pyModeS',
|
||||
|
||||
name="pyModeS",
|
||||
# Versions should comply with PEP440. For a discussion on single-sourcing
|
||||
# the version across setup.py and the project code, see
|
||||
# https://packaging.python.org/en/latest/single_source_version.html
|
||||
version='2.0',
|
||||
|
||||
description='Python ADS-B/Mode-S Decoder',
|
||||
version="2.2",
|
||||
description="Python Mode-S and ADS-B Decoder",
|
||||
long_description=long_description,
|
||||
|
||||
# The project's main homepage.
|
||||
url='https://github.com/junzis/pyModes',
|
||||
|
||||
url="https://github.com/junzis/pyModeS",
|
||||
# Author details
|
||||
author='Junzi Sun',
|
||||
author_email='j.sun-1@tudelft.nl',
|
||||
|
||||
author="Junzi Sun",
|
||||
author_email="j.sun-1@tudelft.nl",
|
||||
# Choose your license
|
||||
license='GNU GPL v3',
|
||||
|
||||
license="GNU GPL v3",
|
||||
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
classifiers=[
|
||||
# How mature is this project? Common values are
|
||||
# 3 - Alpha
|
||||
# 4 - Beta
|
||||
# 5 - Production/Stable
|
||||
'Development Status :: 3 - Alpha',
|
||||
|
||||
"Development Status :: 4 - Beta",
|
||||
# Indicate who your project is intended for
|
||||
'Intended Audience :: Developers',
|
||||
'Topic :: Software Development :: Build Tools',
|
||||
|
||||
"Intended Audience :: Developers",
|
||||
"Topic :: Software Development :: Build Tools",
|
||||
# Pick your license as you wish (should match "license" above)
|
||||
'License :: OSI Approved :: MIT License',
|
||||
|
||||
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
||||
# Specify the Python versions you support here. In particular, ensure
|
||||
# that you indicate whether you support Python 2, Python 3 or both.
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
],
|
||||
|
||||
# What does your project relate to?
|
||||
keywords='Mode-S ADS-B EHS decoding',
|
||||
|
||||
keywords="Mode-S ADS-B EHS decoding",
|
||||
# You can just specify the packages manually here if your project is
|
||||
# simple. Or you can use find_packages().
|
||||
packages=find_packages(exclude=['contrib', 'docs', 'tests']),
|
||||
|
||||
packages=find_packages(exclude=["contrib", "docs", "tests"]),
|
||||
# Alternatively, if you want to distribute just a my_module.py, uncomment
|
||||
# this:
|
||||
# py_modules=["my_module"],
|
||||
|
||||
# List run-time dependencies here. These will be installed by pip when
|
||||
# your project is installed. For an analysis of "install_requires" vs pip's
|
||||
# requirements files see:
|
||||
# https://packaging.python.org/en/latest/requirements.html
|
||||
install_requires=['numpy', 'argparse'],
|
||||
|
||||
install_requires=["numpy", "argparse"],
|
||||
# List additional groups of dependencies here (e.g. development
|
||||
# dependencies). You can install these using the following syntax,
|
||||
# for example:
|
||||
@@ -96,20 +83,17 @@ setup(
|
||||
# 'dev': ['check-manifest'],
|
||||
# 'test': ['coverage'],
|
||||
# },
|
||||
|
||||
# If there are data files included in your packages that need to be
|
||||
# installed, specify them here. If using Python 2.6 or less, then these
|
||||
# have to be included in MANIFEST.in as well.
|
||||
# package_data={
|
||||
# 'sample': ['package_data.dat'],
|
||||
# },
|
||||
|
||||
# Although 'package_data' is the preferred approach, in some case you may
|
||||
# need to place data files outside of your packages. See:
|
||||
# http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files # noqa
|
||||
# In this case, 'data_file' will be installed into '<sys.prefix>/my_data'
|
||||
# data_files=[('my_data', ['data/data_file'])],
|
||||
|
||||
# To provide executable scripts, use entry points in preference to the
|
||||
# "scripts" keyword. Entry points provide cross-platform support and allow
|
||||
# pip to create the appropriate form of executable for the target platform.
|
||||
@@ -118,6 +102,5 @@ setup(
|
||||
# 'sample=sample:main',
|
||||
# ],
|
||||
# },
|
||||
|
||||
scripts=['pyModeS/streamer/modeslive'],
|
||||
scripts=["pyModeS/streamer/modeslive"],
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@ def bds_info(BDS, m):
|
||||
info = [commb.cs20(m)]
|
||||
|
||||
elif BDS == "BDS40":
|
||||
info = (commb.alt40mcp(m), commb.alt40fms(m), commb.p40baro(m))
|
||||
info = (commb.selalt40mcp(m), commb.selalt40fms(m), commb.p40baro(m))
|
||||
|
||||
elif BDS == "BDS44":
|
||||
info = (commb.wind44(m), commb.temp44(m), commb.p44(m), commb.hum44(m))
|
||||
|
||||
@@ -10,12 +10,12 @@ def test_bds20_callsign():
|
||||
|
||||
|
||||
def test_bds40_functions():
|
||||
assert bds.bds40.alt40mcp("A000029C85E42F313000007047D3") == 3008
|
||||
assert bds.bds40.alt40fms("A000029C85E42F313000007047D3") == 3008
|
||||
assert bds.bds40.selalt40mcp("A000029C85E42F313000007047D3") == 3008
|
||||
assert bds.bds40.selalt40fms("A000029C85E42F313000007047D3") == 3008
|
||||
assert bds.bds40.p40baro("A000029C85E42F313000007047D3") == 1020.0
|
||||
|
||||
assert commb.alt40mcp("A000029C85E42F313000007047D3") == 3008
|
||||
assert commb.alt40fms("A000029C85E42F313000007047D3") == 3008
|
||||
assert commb.selalt40mcp("A000029C85E42F313000007047D3") == 3008
|
||||
assert commb.selalt40fms("A000029C85E42F313000007047D3") == 3008
|
||||
assert commb.p40baro("A000029C85E42F313000007047D3") == 1020.0
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +1,32 @@
|
||||
from pyModeS import common
|
||||
|
||||
|
||||
def test_hex2bin():
|
||||
def test_conversions():
|
||||
assert common.hex2bin('6E406B') == "011011100100000001101011"
|
||||
assert common.bin2hex('011011100100000001101011') == "6E406B"
|
||||
assert common.int2hex(11160538) == "AA4BDA"
|
||||
|
||||
def test_crc_decode():
|
||||
checksum = common.crc("8D406B902015A678D4D220AA4BDA")
|
||||
assert checksum == "000000000000000000000000"
|
||||
assert common.crc_legacy("8D406B902015A678D4D220AA4BDA") == 0
|
||||
|
||||
assert common.crc("8D406B902015A678D4D220AA4BDA") == 0
|
||||
assert common.crc('8d8960ed58bf053cf11bc5932b7d') == 0
|
||||
assert common.crc('8d45cab390c39509496ca9a32912') == 0
|
||||
assert common.crc('8d49d3d4e1089d00000000744c3b') == 0
|
||||
assert common.crc('8d74802958c904e6ef4ba0184d5c') == 0
|
||||
assert common.crc('8d4400cd9b0000b4f87000e71a10') == 0
|
||||
assert common.crc('8d4065de58a1054a7ef0218e226a') == 0
|
||||
|
||||
assert common.crc('c80b2dca34aa21dd821a04cb64d4') == 10719924
|
||||
assert common.crc('a800089d8094e33a6004e4b8a522') == 4805588
|
||||
assert common.crc('a8000614a50b6d32bed000bbe0ed') == 5659991
|
||||
assert common.crc('a0000410bc900010a40000f5f477') == 11727682
|
||||
assert common.crc('8d4ca251204994b1c36e60a5343d') == 16
|
||||
assert common.crc('b0001718c65632b0a82040715b65') == 353333
|
||||
|
||||
def test_crc_encode():
|
||||
parity = common.crc("8D406B902015A678D4D220AA4BDA", encode=True)
|
||||
assert common.hex2bin("AA4BDA") == parity
|
||||
assert common.int2hex(parity) == "AA4BDA"
|
||||
|
||||
def test_icao():
|
||||
assert common.icao("8D406B902015A678D4D220AA4BDA") == "406B90"
|
||||
|
||||
Reference in New Issue
Block a user