Ejemplo n.º 1
0
def capability(msg):
    """Decode transponder capability.

    Args:
        msg (str): 14 hexdigits string
    Returns:
        int, str: transponder capability, description

    """
    msgbin = common.hex2bin(msg)
    ca = common.bin2int(msgbin[5:8])

    if ca == 0:
        text = "level 1 transponder"
    elif ca == 4:
        text = "level 2 transponder, ability to set CA to 7, on ground"
    elif ca == 5:
        text = "level 2 transponder, ability to set CA to 7, airborne"
    elif ca == 6:
        text = "evel 2 transponder, ability to set CA to 7, either airborne or ground"
    elif ca == 7:
        text = "Downlink Request value is 0,or the Flight Status is 2, 3, 4 or 5, either airborne or on the ground"
    else:
        text = None

    return ca, text
Ejemplo n.º 2
0
def is30(msg):
    """Check if a message is likely to be BDS code 2,0

    Args:
        msg (str): 28 hexdigits string

    Returns:
        bool: True or False
    """

    if common.allzeros(msg):
        return False

    d = common.hex2bin(common.data(msg))

    if d[0:8] != "00110000":
        return False

    # threat type 3 not assigned
    if d[28:30] == "11":
        return False

    # reserved for ACAS III, in far future
    if common.bin2int(d[15:22]) >= 48:
        return False

    return True
Ejemplo n.º 3
0
def temp44(msg):
    """Static air temperature.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        float, float: temperature and alternative temperature in Celsius degree.
            Note: Two values returns due to what seems to be an inconsistency
            error in ICAO 9871 (2008) Appendix A-67.

    """
    d = common.hex2bin(common.data(msg))

    sign = int(d[23])
    value = common.bin2int(d[24:34])

    if sign:
        value = value - 1024

    temp = value * 0.25  # celsius
    temp = round(temp, 2)

    temp_alternative = value * 0.125  # celsius
    temp_alternative = round(temp_alternative, 3)

    return temp, temp_alternative
Ejemplo n.º 4
0
def is20(msg):
    """Check if a message is likely to be BDS code 2,0

    Args:
        msg (str): 28 hexdigits string

    Returns:
        bool: True or False
    """

    if common.allzeros(msg):
        return False

    d = common.hex2bin(common.data(msg))

    if d[0:8] != "00100000":
        return False

    # allow empty callsign
    if common.bin2int(d[8:56]) == 0
        return True

    if "#" in cs20(msg):
        return False

    return True
Ejemplo n.º 5
0
def sil(msg, version):
    """Calculate SIL, Surveillance Integrity Level

    Args:
        msg (str): 28 hexdigits string with TC = 29, 31

    Returns:
        int or string: Probability of exceeding Horizontal Radius of Containment RCu
        int or string: Probability of exceeding Vertical Integrity Containment Region VPL
        string: SIL supplement based on per "hour" or "sample", or 'unknown'
    """
    tc = typecode(msg)

    if tc not in [29, 31]:
        raise RuntimeError(
            "%s: Not a target state and status message, \
                           or operation status message, expecting TC = 29 or 31"
            % msg
        )

    msgbin = common.hex2bin(msg)

    if tc == 29:
        SIL = common.bin2int(msgbin[76:78])
    elif tc == 31:
        SIL = common.bin2int(msgbin[82:84])

    try:
        PE_RCu = uncertainty.SIL[SIL]["PE_RCu"]
        PE_VPL = uncertainty.SIL[SIL]["PE_VPL"]
    except KeyError:
        PE_RCu, PE_VPL = uncertainty.NA, uncertainty.NA

    base = "unknown"

    if version == 2:
        if tc == 29:
            SIL_SUP = common.bin2int(msgbin[39])
        elif tc == 31:
            SIL_SUP = common.bin2int(msgbin[86])

        if SIL_SUP == 0:
            base = "hour"
        elif SIL_SUP == 1:
            base = "sample"

    return PE_RCu, PE_VPL, base
Ejemplo n.º 6
0
def airborne_position_with_ref(msg, lat_ref, lon_ref):
    """Decode airborne position with only one message,
    knowing reference nearby location, such as previously calculated location,
    ground station, or airport location, etc. The reference position shall
    be with in 180NM 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
    """

    mb = common.hex2bin(msg)[32:]

    cprlat = common.bin2int(mb[22:39]) / 131072
    cprlon = common.bin2int(mb[39:56]) / 131072

    i = int(mb[21])
    d_lat = 360 / 59 if i else 360 / 60

    j = common.floor(lat_ref / d_lat) + common.floor(
        0.5 + ((lat_ref % d_lat) / d_lat) - cprlat
    )

    lat = d_lat * (j + cprlat)

    ni = common.cprNL(lat) - i

    if ni > 0:
        d_lon = 360 / ni
    else:
        d_lon = 360

    m = common.floor(lon_ref / d_lon) + common.floor(
        0.5 + ((lon_ref % d_lon) / d_lon) - cprlon
    )

    lon = d_lon * (m + cprlon)

    return round(lat, 5), round(lon, 5)
Ejemplo n.º 7
0
def wind44(msg):
    """Wind speed and direction.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        (int, float): speed (kt), direction (degree)

    """
    d = common.hex2bin(common.data(msg))

    status = int(d[4])
    if not status:
        return None, None

    speed = common.bin2int(d[5:14])  # knots
    direction = common.bin2int(d[14:23]) * 180 / 256  # degree

    return round(speed, 0), round(direction, 1)
Ejemplo n.º 8
0
def wind44(msg):
    """Wind speed and direction.

    Args:
        msg (String): 28 bytes hexadecimal message string

    Returns:
        (int, float): speed (kt), direction (degree)

    """
    d = common.hex2bin(common.data(msg))

    status = int(d[4])
    if not status:
        return None, None

    speed = common.bin2int(d[5:14])  # knots
    direction = common.bin2int(d[14:23]) * 180.0 / 256.0  # degree

    return round(speed, 0), round(direction, 1)
Ejemplo n.º 9
0
def is40(msg):
    """Check if a message is likely to be BDS code 4,0

    Args:
        msg (String): 28 bytes hexadecimal message string

    Returns:
        bool: True or False
    """

    if common.allzeros(msg):
        return False

    d = common.hex2bin(common.data(msg))

    # status bit 1, 14, and 27

    if common.wrongstatus(d, 1, 2, 13):
        return False

    if common.wrongstatus(d, 14, 15, 26):
        return False

    if common.wrongstatus(d, 27, 28, 39):
        return False

    if common.wrongstatus(d, 48, 49, 51):
        return False

    if common.wrongstatus(d, 54, 55, 56):
        return False

    # bits 40-47 and 52-53 shall all be zero

    if common.bin2int(d[39:47]) != 0:
        return False

    if common.bin2int(d[51:53]) != 0:
        return False

    return True
Ejemplo n.º 10
0
def is45(msg):
    """Check if a message is likely to be BDS code 4,5.

    Meteorological hazard report

    Args:
        msg (str): 28 hexdigits string

    Returns:
        bool: True or False

    """
    if common.allzeros(msg):
        return False

    d = common.hex2bin(common.data(msg))

    # status bit 1, 4, 7, 10, 13, 16, 27, 39
    if common.wrongstatus(d, 1, 2, 3):
        return False

    if common.wrongstatus(d, 4, 5, 6):
        return False

    if common.wrongstatus(d, 7, 8, 9):
        return False

    if common.wrongstatus(d, 10, 11, 12):
        return False

    if common.wrongstatus(d, 13, 14, 15):
        return False

    if common.wrongstatus(d, 16, 17, 26):
        return False

    if common.wrongstatus(d, 27, 28, 38):
        return False

    if common.wrongstatus(d, 39, 40, 51):
        return False

    # reserved
    if common.bin2int(d[51:56]) != 0:
        return False

    temp = temp45(msg)
    if temp:
        if temp > 60 or temp < -80:
            return False

    return True
Ejemplo n.º 11
0
def target_angle(msg):
    """Decode target heading/track angle.

    Args:
        msg (str): 28 bytes hexadecimal message string

    Returns:
        int: Target angle (degree)
        string: Angle type ('Heading' or 'Track')
        string: Source ('MCP/FCU', 'Autopilot Mode' or 'FMS/RNAV')
    
    """

    if common.typecode(msg) != 29:
        raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)

    mb = common.hex2bin(msg)[32:]

    subtype = common.bin2int(mb[5:7])

    if subtype == 1:
        raise RuntimeError("%s: ADS-B version 2 target state and status message does not contain target angle, use selected heading instead" % msg)

    angle_avail = common.bin2int(mb[25:27])
    if angle_avail == 0:
        angle = None
    else:
        angle = common.bin2int(mb[27:36])

        if angle_avail == 1:
            angle_source = "MCP/FCU"
        elif angle_avail == 2:
            angle_source = "Autopilot mode"
        else:
            angle_source = "FMS/RNAV"
        
        angle_type = "Heading" if int(mb[36]) else "Track"

    return angle, angle_type, angle_source
Ejemplo n.º 12
0
def target_altitude(msg):
    """Decode target altitude.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: Target altitude (ft)
        string: Source ('MCP/FCU', 'Holding mode' or 'FMS/RNAV')
        string: Altitude reference, either pressure altitude or barometric corrected altitude ('FL' or 'MSL')

    """

    if common.typecode(msg) != 29:
        raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)

    mb = common.hex2bin(msg)[32:]

    subtype = common.bin2int(mb[5:7])

    if subtype == 1:
        raise RuntimeError("%s: ADS-B version 2 target state and status message does not contain target altitude, use selected altitude instead" % msg)

    alt_avail = common.bin2int(mb[7:9])
    if alt_avail == 0:
        return None
    elif alt_avail == 1:
        alt_source = "MCP/FCU"
    elif alt_avail == 2:
        alt_source = "Holding mode"
    else:
        alt_source = "FMS/RNAV"

    alt_ref = "FL" if int(mb[9]) == 0 else "MSL"

    alt = -1000 + common.bin2int(mb[15:25]) * 100

    return alt, alt_source, alt_ref
Ejemplo n.º 13
0
def um(msg):
    """Decode utility message.

    Utility message contains interrogator identifier and reservation type.

    Args:
        msg (str): 14 hexdigits string
    Returns:
        int, str: interrogator identifier code that triggered the reply, and
        reservation type made by the interrogator
    """
    msgbin = common.hex2bin(msg)
    iis = common.bin2int(msgbin[13:17])
    ids = common.bin2int(msgbin[17:19])
    if ids == 0:
        ids_text = None
    if ids == 1:
        ids_text = "Comm-B interrogator identifier code"
    if ids == 2:
        ids_text = "Comm-C interrogator identifier code"
    if ids == 3:
        ids_text = "Comm-D interrogator identifier code"
    return iis, ids, ids_text
Ejemplo n.º 14
0
def p45(msg):
    """Average static pressure.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: static pressure in hPa

    """
    d = common.hex2bin(common.data(msg))
    if d[26] == "0":
        return None
    p = common.bin2int(d[27:38])  # hPa
    return p
Ejemplo n.º 15
0
def rh45(msg):
    """Radio height.

    Args:
        msg (String): 28 bytes hexadecimal message string

    Returns:
        int: radio height in ft

    """
    d = common.hex2bin(common.data(msg))
    if d[38] == "0":
        return None
    rh = common.bin2int(d[39:51]) * 16
    return rh
Ejemplo n.º 16
0
def p45(msg):
    """Average static pressure.

    Args:
        msg (String): 28 bytes hexadecimal message string

    Returns:
        int: static pressure in hPa

    """
    d = common.hex2bin(common.data(msg))
    if d[26] == "0":
        return None
    p = common.bin2int(d[27:38])  # hPa
    return p
Ejemplo n.º 17
0
def rh45(msg):
    """Radio height.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: radio height in ft

    """
    d = common.hex2bin(common.data(msg))
    if d[38] == "0":
        return None
    rh = common.bin2int(d[39:51]) * 16
    return rh
Ejemplo n.º 18
0
def gs50(msg):
    """Ground speed, BDS 5,0 message

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: ground speed in knots
    """
    d = common.hex2bin(common.data(msg))

    if d[23] == "0":
        return None

    spd = common.bin2int(d[24:34]) * 2  # kts
    return spd
Ejemplo n.º 19
0
def tas50(msg):
    """Aircraft true airspeed, BDS 5,0 message

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: true airspeed in knots
    """
    d = common.hex2bin(common.data(msg))

    if d[45] == "0":
        return None

    tas = common.bin2int(d[46:56]) * 2  # kts
    return tas
Ejemplo n.º 20
0
def mach60(msg):
    """Aircraft MACH number

    Args:
        msg (str): 28 hexdigits string

    Returns:
        float: MACH number
    """
    d = common.hex2bin(common.data(msg))

    if d[23] == "0":
        return None

    mach = common.bin2int(d[24:34]) * 2.048 / 512.0
    return round(mach, 3)
Ejemplo n.º 21
0
def wv45(msg):
    """Wake vortex.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: Wake vortex level. 0=NIL, 1=Light, 2=Moderate, 3=Severe

    """
    d = common.hex2bin(common.data(msg))
    if d[12] == "0":
        return None

    ws = common.bin2int(d[13:15])
    return ws
Ejemplo n.º 22
0
def tas53(msg):
    """Aircraft true airspeed, BDS 5,3 message

    Args:
        msg (String): 28 bytes hexadecimal message

    Returns:
        float: true airspeed in knots
    """
    d = common.hex2bin(common.data(msg))

    if d[33] == "0":
        return None

    tas = common.bin2int(d[34:46]) * 0.5  # kts
    return round(tas, 1)
Ejemplo n.º 23
0
def ias53(msg):
    """Indicated airspeed, DBS 5,3 message

    Args:
        msg (String): 28 bytes hexadecimal message

    Returns:
        int: indicated arispeed in knots
    """
    d = common.hex2bin(common.data(msg))

    if d[12] == "0":
        return None

    ias = common.bin2int(d[13:23])  # knots
    return ias
Ejemplo n.º 24
0
def mach53(msg):
    """MACH number, DBS 5,3 message

    Args:
        msg (String): 28 bytes hexadecimal message

    Returns:
        float: MACH number
    """
    d = common.hex2bin(common.data(msg))

    if d[23] == "0":
        return None

    mach = common.bin2int(d[24:33]) * 0.008
    return round(mach, 3)
Ejemplo n.º 25
0
def tas50(msg):
    """Aircraft true airspeed, BDS 5,0 message

    Args:
        msg (String): 28 bytes hexadecimal message (BDS50) string

    Returns:
        int: true airspeed in knots
    """
    d = common.hex2bin(common.data(msg))

    if d[45] == "0":
        return None

    tas = common.bin2int(d[46:56]) * 2  # kts
    return tas
Ejemplo n.º 26
0
def gs50(msg):
    """Ground speed, BDS 5,0 message

    Args:
        msg (String): 28 bytes hexadecimal message (BDS50) string

    Returns:
        int: ground speed in knots
    """
    d = common.hex2bin(common.data(msg))

    if d[23] == "0":
        return None

    spd = common.bin2int(d[24:34]) * 2  # kts
    return spd
Ejemplo n.º 27
0
def mb45(msg):
    """Microburst.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: Microburst level. 0=NIL, 1=Light, 2=Moderate, 3=Severe

    """
    d = common.hex2bin(common.data(msg))
    if d[6] == "0":
        return None

    mb = common.bin2int(d[7:9])
    return mb
Ejemplo n.º 28
0
def ws45(msg):
    """Wind shear.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: Wind shear level. 0=NIL, 1=Light, 2=Moderate, 3=Severe

    """
    d = common.hex2bin(common.data(msg))
    if d[3] == "0":
        return None

    ws = common.bin2int(d[4:6])
    return ws
Ejemplo n.º 29
0
def ias60(msg):
    """Indicated airspeed

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: indicated airspeed in knots
    """
    d = common.hex2bin(common.data(msg))

    if d[12] == "0":
        return None

    ias = common.bin2int(d[13:23])  # kts
    return ias
Ejemplo n.º 30
0
def turb45(msg):
    """Turbulence.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: Turbulence level. 0=NIL, 1=Light, 2=Moderate, 3=Severe

    """
    d = common.hex2bin(common.data(msg))
    if d[0] == "0":
        return None

    turb = common.bin2int(d[1:3])
    return turb