2018-07-26 02:09:28 +08:00
|
|
|
The Python ADS-B/Mode-S Decoder
|
2017-12-21 00:00:02 +08:00
|
|
|
==========================================
|
2016-03-17 06:11:15 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
Python library for ADS-B/Mode-S message decoding. Supported Downlink Formats (DF) are:
|
2016-03-17 06:11:15 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
**DF17 / DF18: Automatic Dependent Surveillance - Broadcast (ADS-B)**
|
2016-03-17 06:11:15 +08:00
|
|
|
|
2018-06-21 04:25:47 +08:00
|
|
|
- TC=1-4 / BDS 0,8: Aircraft identification and category
|
|
|
|
- TC=5-8 / BDS 0,6: Surface position
|
|
|
|
- TC=9-18 / BDS 0,5: Airborne position
|
|
|
|
- TC=19 / BDS 0,9: Airborne velocity
|
|
|
|
- TC=28 / BDS 6,1: Airborne status [to be implemented]
|
|
|
|
- TC=29 / BDS 6,2: Target state and status information [to be implemented]
|
|
|
|
- TC=31 / BDS 6,5: Aircraft operational status [to be implemented]
|
2017-07-21 23:45:08 +08:00
|
|
|
|
2017-03-23 04:07:59 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
**DF20 / DF21: Mode-S Comm-B replies**
|
2018-06-21 04:22:42 +08:00
|
|
|
|
2018-06-21 04:25:47 +08:00
|
|
|
- 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 5,0: Track and turn report
|
|
|
|
- BDS 5,3: Air-referenced state vector
|
|
|
|
- BDS 6,0: Heading and speed report
|
2018-06-21 04:22:42 +08:00
|
|
|
|
|
|
|
|
2018-06-21 04:25:47 +08:00
|
|
|
**DF4 / DF20: Altitude code**
|
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
**DF5 / DF21: Identity code (squawk code)**
|
2016-03-17 06:11:15 +08:00
|
|
|
|
2017-09-19 17:19:54 +08:00
|
|
|
Detailed manual on Mode-S decoding is published by the author, at:
|
2018-06-21 04:22:42 +08:00
|
|
|
https://mode-s.org/decode
|
2016-03-17 06:11:15 +08:00
|
|
|
|
|
|
|
|
2017-12-21 00:00:02 +08:00
|
|
|
New features in v2.0
|
|
|
|
---------------------
|
2018-03-28 19:31:24 +08:00
|
|
|
- New structure of the libraries
|
2018-06-21 04:22:42 +08:00
|
|
|
- ADS-B and Comm-B data streaming
|
2018-06-23 07:24:15 +08:00
|
|
|
- Active aircraft viewing (terminal curses)
|
2018-06-21 04:22:42 +08:00
|
|
|
- Improved BDS identification
|
|
|
|
- Optimizing decoding speed
|
2017-12-21 00:00:02 +08:00
|
|
|
|
|
|
|
|
2016-03-17 06:11:15 +08:00
|
|
|
Source code
|
|
|
|
-----------
|
2018-07-26 02:09:28 +08:00
|
|
|
Checkout and contribute to this open-source project at:
|
2018-06-21 04:22:42 +08:00
|
|
|
https://github.com/junzis/pyModeS
|
2016-03-17 06:11:15 +08:00
|
|
|
|
2016-10-19 22:22:28 +08:00
|
|
|
API documentation at:
|
2016-08-16 23:07:02 +08:00
|
|
|
http://pymodes.readthedocs.io
|
2018-03-28 19:31:24 +08:00
|
|
|
[To be updated]
|
2016-03-17 06:11:15 +08:00
|
|
|
|
2017-09-19 17:19:54 +08:00
|
|
|
|
2016-03-17 06:11:15 +08:00
|
|
|
Install
|
|
|
|
-------
|
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
To install latest version from the GitHub:
|
2017-12-13 04:48:25 +08:00
|
|
|
|
|
|
|
::
|
|
|
|
|
2018-06-21 04:22:42 +08:00
|
|
|
pip install git+https://github.com/junzis/pyModeS
|
2017-12-13 04:48:25 +08:00
|
|
|
|
2017-09-19 17:19:54 +08:00
|
|
|
|
2018-06-23 07:28:41 +08:00
|
|
|
|
2018-07-05 02:56:11 +08:00
|
|
|
Live view traffic (modeslive)
|
2018-06-23 07:28:41 +08:00
|
|
|
----------------------------------------------------
|
2018-06-23 21:19:29 +08:00
|
|
|
Supports **Mode-S Beast** and **AVR** raw stream
|
2018-06-23 07:28:41 +08:00
|
|
|
|
2018-06-23 07:29:58 +08:00
|
|
|
::
|
2018-06-23 07:28:41 +08:00
|
|
|
|
2019-01-22 16:52:01 +08:00
|
|
|
modeslive --server [server_address] --port [tcp_port] --rawtype [beast,avr,skysense] --latlon [lat] [lon]
|
2018-06-23 21:19:29 +08:00
|
|
|
|
|
|
|
Arguments:
|
|
|
|
-h, --help show this help message and exit
|
|
|
|
--server SERVER server address or IP
|
|
|
|
--port PORT raw data port
|
2019-01-22 16:52:01 +08:00
|
|
|
--rawtype RAWTYPE beast, avr or skysense
|
2018-06-23 21:19:29 +08:00
|
|
|
--latlon LAT LON receiver position
|
2018-07-05 03:20:23 +08:00
|
|
|
--show-uncertainty display uncertaint values, default off
|
2018-06-23 07:28:41 +08:00
|
|
|
|
|
|
|
|
2018-06-29 20:13:20 +08:00
|
|
|
If you have a RTL-SDR receiver or Mode-S Beast, use modesmixer2 (http://xdeco.org/?page_id=48) to create raw beast TCP stream:
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
$ modesmixer2 --inSeriel port[:speed[:flow_control]] --outServer beast:[tcp_port]
|
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
Example screenshot:
|
2018-06-23 22:05:06 +08:00
|
|
|
|
2018-07-05 02:56:11 +08:00
|
|
|
.. image:: https://github.com/junzis/pyModeS/raw/master/doc/modeslive-screenshot.png
|
2018-06-23 22:05:06 +08:00
|
|
|
:width: 700px
|
2018-06-23 07:28:41 +08:00
|
|
|
|
2017-09-19 17:19:54 +08:00
|
|
|
Use the library
|
|
|
|
---------------
|
2016-03-17 06:11:15 +08:00
|
|
|
|
|
|
|
.. code:: python
|
|
|
|
|
2017-11-01 18:53:10 +08:00
|
|
|
import pyModeS as pms
|
2016-03-17 06:11:15 +08:00
|
|
|
|
2016-03-23 18:45:38 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
Common functions
|
2017-07-21 23:40:10 +08:00
|
|
|
*****************
|
2016-03-23 18:45:38 +08:00
|
|
|
|
|
|
|
.. code:: python
|
|
|
|
|
2017-11-01 18:53:10 +08:00
|
|
|
pms.df(msg) # Downlink Format
|
2018-03-28 19:31:24 +08:00
|
|
|
pms.icao(msg) # Infer the ICAO address from the message
|
2017-11-01 18:53:10 +08:00
|
|
|
pms.crc(msg, encode=False) # Perform CRC or generate parity bit
|
2016-03-23 18:45:38 +08:00
|
|
|
|
2018-03-28 19:31:24 +08:00
|
|
|
pms.hex2bin(str) # Convert hexadecimal string to binary string
|
|
|
|
pms.bin2int(str) # Convert binary string to integer
|
|
|
|
pms.hex2int(str) # Convert hexadecimal string to integer
|
|
|
|
pms.gray2int(str) # Convert grey code to interger
|
2017-07-21 23:40:10 +08:00
|
|
|
|
2016-03-23 18:45:38 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
Core functions for ADS-B decoding
|
|
|
|
*********************************
|
2016-03-17 06:11:15 +08:00
|
|
|
|
|
|
|
.. code:: python
|
|
|
|
|
2017-11-01 18:53:10 +08:00
|
|
|
pms.adsb.icao(msg)
|
|
|
|
pms.adsb.typecode(msg)
|
2016-10-19 22:22:28 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
# Typecode 1-4
|
2017-11-01 18:53:10 +08:00
|
|
|
pms.adsb.callsign(msg)
|
2016-10-19 22:22:28 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
# Typecode 5-8 (surface), 9-18 (airborne, barometric height), and 9-18 (airborne, GNSS height)
|
2017-11-01 18:53:10 +08:00
|
|
|
pms.adsb.position(msg_even, msg_odd, t_even, t_odd, lat_ref=None, lon_ref=None)
|
|
|
|
pms.adsb.airborne_position(msg_even, msg_odd, t_even, t_odd)
|
|
|
|
pms.adsb.surface_position(msg_even, msg_odd, t_even, t_odd, lat_ref, lon_ref)
|
2016-10-19 22:22:28 +08:00
|
|
|
|
2017-11-01 18:53:10 +08:00
|
|
|
pms.adsb.position_with_ref(msg, lat_ref, lon_ref)
|
|
|
|
pms.adsb.airborne_position_with_ref(msg, lat_ref, lon_ref)
|
|
|
|
pms.adsb.surface_position_with_ref(msg, lat_ref, lon_ref)
|
2017-03-07 20:41:07 +08:00
|
|
|
|
2017-11-01 18:53:10 +08:00
|
|
|
pms.adsb.altitude(msg)
|
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
# Typecode: 19
|
|
|
|
pms.adsb.velocity(msg) # Handles both surface & airborne messages
|
|
|
|
pms.adsb.speed_heading(msg) # Handles both surface & airborne messages
|
2017-11-01 18:53:10 +08:00
|
|
|
pms.adsb.surface_velocity(msg)
|
|
|
|
pms.adsb.airborne_velocity(msg)
|
2017-03-07 20:41:07 +08:00
|
|
|
|
2016-03-17 06:11:15 +08:00
|
|
|
|
2017-09-19 17:19:54 +08:00
|
|
|
Note: When you have a fix position of the aircraft, it is convenient to
|
2016-10-19 22:22:28 +08:00
|
|
|
use `position_with_ref()` method to decode with only one position message
|
|
|
|
(either odd or even). This works with both airborne and surface position
|
|
|
|
messages. But the reference position shall be with in 180NM (airborne)
|
2017-07-21 23:40:10 +08:00
|
|
|
or 45NM (surface) of the true position.
|
|
|
|
|
2018-03-28 19:31:24 +08:00
|
|
|
|
2018-06-21 23:38:59 +08:00
|
|
|
Decode altitude replies in DF4 / DF20
|
|
|
|
**************************************
|
|
|
|
.. code:: python
|
|
|
|
|
|
|
|
pms.common.altcode(msg) # Downlink format must be 4 or 20
|
|
|
|
|
|
|
|
|
|
|
|
Decode identity replies in DF5 / DF21
|
|
|
|
**************************************
|
|
|
|
.. code:: python
|
|
|
|
|
|
|
|
pms.common.idcode(msg) # Downlink format must be 5 or 21
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-28 19:31:24 +08:00
|
|
|
Common Mode-S functions
|
|
|
|
************************
|
2017-07-21 23:40:10 +08:00
|
|
|
|
|
|
|
.. code:: python
|
|
|
|
|
2018-03-28 19:31:24 +08:00
|
|
|
pms.icao(msg) # Infer the ICAO address from the message
|
2018-07-26 02:09:28 +08:00
|
|
|
pms.bds.infer(msg) # Infer the Modes-S BDS register
|
2017-07-21 23:40:10 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
# Check if BDS is 5,0 or 6,0, give reference speed, track, altitude (from ADS-B)
|
2018-03-28 19:31:24 +08:00
|
|
|
pms.bds.is50or60(msg, spd_ref, trk_ref, alt_ref)
|
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
# Check each BDS explicitly
|
2018-06-23 21:54:17 +08:00
|
|
|
pms.bds.bds10.is10(msg)
|
|
|
|
pms.bds.bds17.is17(msg)
|
|
|
|
pms.bds.bds20.is20(msg)
|
|
|
|
pms.bds.bds30.is30(msg)
|
|
|
|
pms.bds.bds40.is40(msg)
|
|
|
|
pms.bds.bds44.is44(msg)
|
|
|
|
pms.bds.bds50.is50(msg)
|
|
|
|
pms.bds.bds60.is60(msg)
|
|
|
|
|
|
|
|
|
2018-03-28 19:31:24 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
Mode-S Elementary Surveillance (ELS)
|
2018-03-28 19:31:24 +08:00
|
|
|
*************************************
|
2016-03-17 06:11:15 +08:00
|
|
|
|
|
|
|
.. code:: python
|
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
pms.commb.ovc10(msg) # Overlay capability, BDS 1,0
|
2018-05-17 16:40:22 +08:00
|
|
|
pms.commb.cap17(msg) # GICB capability, BDS 1,7
|
2018-07-26 02:09:28 +08:00
|
|
|
pms.commb.cs20(msg) # Callsign, BDS 2,0
|
2017-11-01 18:53:10 +08:00
|
|
|
|
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
Mode-S Enhanced Surveillance (EHS)
|
2018-03-28 19:31:24 +08:00
|
|
|
***********************************
|
|
|
|
|
|
|
|
.. code:: python
|
2017-11-01 18:53:10 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
# For BDS register 4,0
|
2018-05-17 16:40:22 +08:00
|
|
|
pms.commb.alt40mcp(msg) # MCP/FCU selected altitude (ft)
|
|
|
|
pms.commb.alt40fms(msg) # FMS selected altitude (ft)
|
|
|
|
pms.commb.p40baro(msg) # Barometric pressure (mb)
|
2017-11-01 18:53:10 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
# For BDS register 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)
|
2017-11-01 18:53:10 +08:00
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
# For BDS register 6,0
|
|
|
|
pms.commb.hdg60(msg) # Magnetic heading (deg)
|
|
|
|
pms.commb.ias60(msg) # Indicated airspeed (kt)
|
|
|
|
pms.commb.mach60(msg) # Mach number (-)
|
|
|
|
pms.commb.vr60baro(msg) # Barometric altitude rate (ft/min)
|
|
|
|
pms.commb.vr60ins(msg) # Inertial vertical speed (ft/min)
|
2016-03-17 06:11:15 +08:00
|
|
|
|
2018-03-28 19:31:24 +08:00
|
|
|
|
|
|
|
Meteorological routine air report (MRAR) [Experimental]
|
|
|
|
*******************************************************
|
|
|
|
|
|
|
|
.. code:: python
|
|
|
|
|
2018-07-26 02:09:28 +08:00
|
|
|
# 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 (%)
|
2018-03-28 19:31:24 +08:00
|
|
|
|
2018-06-23 21:54:17 +08:00
|
|
|
|
2016-09-12 11:48:43 +08:00
|
|
|
Developement
|
|
|
|
------------
|
2017-09-19 17:19:54 +08:00
|
|
|
To perform unit tests. First install ``tox`` through pip, Then, run the following commands:
|
2017-11-01 18:53:10 +08:00
|
|
|
|
|
|
|
.. code:: bash
|
|
|
|
|
|
|
|
$ tox
|