"""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`` """ import pyModeS as pms from pyModeS import common from pyModeS.decoder import uncertainty # from pyModeS.decoder.bds import bds05, bds06, bds09 from pyModeS.decoder.bds.bds05 import ( airborne_position, airborne_position_with_ref, altitude as altitude05, ) from pyModeS.decoder.bds.bds06 import ( surface_position, surface_position_with_ref, surface_velocity, ) from pyModeS.decoder.bds.bds08 import category, callsign from pyModeS.decoder.bds.bds09 import airborne_velocity, altitude_diff def df(msg): return common.df(msg) def icao(msg): return common.icao(msg) def typecode(msg): return common.typecode(msg) def position(msg0, msg1, t0, t1, lat_ref=None, lon_ref=None): """Decode position from a pair of even and odd position message. Works with both airborne and surface position messages. Args: msg0 (string): even message (28 hexdigits) msg1 (string): odd message (28 hexdigits) t0 (int): timestamps for the even message t1 (int): timestamps for the odd message Returns: (float, float): (latitude, longitude) of the aircraft """ tc0 = typecode(msg0) tc1 = typecode(msg1) if 5 <= tc0 <= 8 and 5 <= tc1 <= 8: if (not lat_ref) or (not lon_ref): raise RuntimeError( "Surface position encountered, a reference \ position lat/lon required. Location of \ receiver can be used." ) else: return surface_position(msg0, msg1, t0, t1, lat_ref, lon_ref) elif 9 <= tc0 <= 18 and 9 <= tc1 <= 18: # Airborne position with barometric height return airborne_position(msg0, msg1, t0, t1) elif 20 <= tc0 <= 22 and 20 <= tc1 <= 22: # Airborne position with GNSS height return airborne_position(msg0, msg1, t0, t1) else: raise RuntimeError("incorrect or inconsistent message types") def position_with_ref(msg, lat_ref, lon_ref): """Decode position with only one message. A reference position is required, which can be previously calculated location, ground station, or airport location. The function works with both airborne and surface position messages. The reference position shall be with in 180NM (airborne) or 45NM (surface) of the true position. Args: msg (str): even message (28 hexdigits) lat_ref: previous known latitude lon_ref: previous known longitude Returns: (float, float): (latitude, longitude) of the aircraft """ tc = typecode(msg) if 5 <= tc <= 8: return surface_position_with_ref(msg, lat_ref, lon_ref) elif 9 <= tc <= 18 or 20 <= tc <= 22: return airborne_position_with_ref(msg, lat_ref, lon_ref) else: raise RuntimeError("incorrect or inconsistent message types") def altitude(msg): """Decode aircraft altitude. Args: msg (str): 28 hexdigits string Returns: int: altitude in feet """ tc = typecode(msg) if tc < 5 or tc == 19 or tc > 22: raise RuntimeError("%s: Not a position message" % msg) elif tc >= 5 and tc <= 8: # surface position, altitude 0 return 0 else: # airborn position return altitude05(msg) def velocity(msg, source=False): """Calculate the speed, heading, and vertical rate (handles both airborne or surface message). Args: msg (str): 28 hexdigits string source (boolean): Include direction and vertical rate sources in return. Default to False. If set to True, the function will return six value instead of four. Returns: int, float, int, string, [string], [string]: Four or six parameters, including: - Speed (kt) - Angle (degree), either ground track or heading - Vertical rate (ft/min) - Speed type ('GS' for ground speed, 'AS' for airspeed) - [Optional] Direction source ('TRUE_NORTH' or 'MAGENTIC_NORTH') - [Optional] Vertical rate source ('BARO' or 'GNSS') For surface messages, vertical rate and its respective sources are set to None. """ if 5 <= typecode(msg) <= 8: return surface_velocity(msg, source) elif typecode(msg) == 19: return airborne_velocity(msg, source) else: raise RuntimeError( "incorrect or inconsistent message types, expecting 4 22: raise RuntimeError( "%s: Not a surface position message (5 22: raise RuntimeError( "%s: Not a surface position message (5 22: raise RuntimeError( "%s: Not a surface position message (5 18: raise RuntimeError( "%s: Not a airborne position message, expecting 8