示例#1
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
示例#2
0
def nac_v(msg):
    """Calculate NACv, Navigation Accuracy Category - Velocity

    Args:
        msg (str): 28 hexdigits string, TC = 19

    Returns:
        int or string: 95% horizontal accuracy bounds for velocity, Horizontal Figure of Merit
        int or string: 95% vertical accuracy bounds for velocity, Vertical Figure of Merit
    """
    tc = typecode(msg)

    if tc != 19:
        raise RuntimeError(
            "%s: Not an airborne velocity message, expecting TC = 19" % msg)

    msgbin = common.hex2bin(msg)
    NACv = common.bin2int(msgbin[42:45])

    try:
        HFOMr = uncertainty.NACv[NACv]["HFOMr"]
        VFOMr = uncertainty.NACv[NACv]["VFOMr"]
    except KeyError:
        HFOMr, VFOMr = uncertainty.NA, uncertainty.NA

    return HFOMr, VFOMr
示例#3
0
def lnav_mode(msg) -> bool:
    """Decode LNAV mode.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        bool: LNAV mode engaged

    """

    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 == 0:
        raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain lnav mode, use horizontal mode instead" % msg)

    if int(mb[46]) == 0:
        return None

    lnav_mode = True if int(mb[53]) == 1 else False

    return lnav_mode
示例#4
0
文件: surv.py 项目: wrobell/pyModeS
def fs(msg):
    """Decode flight status.

    Args:
        msg (str): 14 hexdigits string
    Returns:
        int, str: flight status, description

    """
    msgbin = common.hex2bin(msg)
    fs = common.bin2int(msgbin[5:8])
    text = None

    if fs == 0:
        text = "no alert, no SPI, aircraft is airborne"
    elif fs == 1:
        text = "no alert, no SPI, aircraft is on-ground"
    elif fs == 2:
        text = "alert, no SPI, aircraft is airborne"
    elif fs == 3:
        text = "alert, no SPI, aircraft is on-ground"
    elif fs == 4:
        text = "alert, SPI, aircraft is airborne or on-ground"
    elif fs == 5:
        text = "no alert, SPI, aircraft is airborne or on-ground"

    return fs, text
示例#5
0
def nuc_v(msg):
    """Calculate NUCv, Navigation Uncertainty Category - Velocity (ADS-B version 1)

    Args:
        msg (str): 28 hexdigits string,

    Returns:
        int or string: 95% Horizontal Velocity Error
        int or string: 95% Vertical Velocity Error
    """
    tc = typecode(msg)

    if tc != 19:
        raise RuntimeError(
            "%s: Not an airborne velocity message, expecting TC = 19" % msg)

    msgbin = common.hex2bin(msg)
    NUCv = common.bin2int(msgbin[42:45])

    try:
        HVE = uncertainty.NUCv[NUCv]["HVE"]
        VVE = uncertainty.NUCv[NUCv]["VVE"]
    except KeyError:
        HVE, VVE = uncertainty.NA, uncertainty.NA

    return HVE, VVE
示例#6
0
def altitude(msg):
    """Decode aircraft altitude

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: altitude in feet
    """

    tc = common.typecode(msg)

    if tc < 9 or tc == 19 or tc > 22:
        raise RuntimeError("%s: Not a airborn position message" % msg)

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

    if tc < 19:
        altcode = altbin[0:6] + "0" + altbin[6:]
        alt = common.altitude(altcode)
    else:
        alt = common.bin2int(altbin) * 3.28084

    return alt
示例#7
0
文件: bds08.py 项目: wrobell/pyModeS
def callsign(msg):
    """Aircraft callsign

    Args:
        msg (str): 28 hexdigits string

    Returns:
        string: callsign
    """

    if common.typecode(msg) < 1 or common.typecode(msg) > 4:
        raise RuntimeError("%s: Not a identification message" % msg)

    chars = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######"
    msgbin = common.hex2bin(msg)
    csbin = msgbin[40:96]

    cs = ""
    cs += chars[common.bin2int(csbin[0:6])]
    cs += chars[common.bin2int(csbin[6:12])]
    cs += chars[common.bin2int(csbin[12:18])]
    cs += chars[common.bin2int(csbin[18:24])]
    cs += chars[common.bin2int(csbin[24:30])]
    cs += chars[common.bin2int(csbin[30:36])]
    cs += chars[common.bin2int(csbin[36:42])]
    cs += chars[common.bin2int(csbin[42:48])]

    # clean string, remove spaces and marks, if any.
    # cs = cs.replace('_', '')
    cs = cs.replace("#", "")
    return cs
示例#8
0
def emergency_state(msg: str) -> int:
    """Decode aircraft emergency state.

    Value   Meaning
    -----   -----------------------
    0       No emergency
    1       General emergency
    2       Lifeguard/Medical
    3       Minimum fuel
    4       No communications
    5       Unlawful communications
    6-7     Reserved

    :param msg: 28 bytes hexadecimal message string
    :return: emergency state
    """

    mb = common.hex2bin(msg)[32:]
    subtype = common.bin2int(mb[5:8])

    if subtype == 2:
        raise RuntimeError("%s: Emergency message is ACAS-RA, not implemented")

    emergency_state = common.bin2int(mb[8:11])
    return emergency_state
示例#9
0
def is_emergency(msg: str) -> bool:
    """Check if the aircraft is reporting an emergency.

    Non-emergencies are either a subtype of zero (no information) or
    subtype of one and a value of zero (no emergency).
    Subtype = 2 indicates an ACAS RA broadcast, look in BDS 3,0

    :param msg: 28 bytes hexadecimal message string
    :return: if the aircraft has declared an emergency
    """
    if common.typecode(msg) != 28:
        raise RuntimeError(
            "%s: Not an airborne status message, expecting TC=28" % msg)

    mb = common.hex2bin(msg)[32:]
    subtype = common.bin2int(mb[5:8])

    if subtype == 2:
        raise RuntimeError("%s: Emergency message is ACAS-RA, not implemented")

    emergency_state = common.bin2int(mb[8:11])

    if subtype == 1 and emergency_state == 1:
        return True
    else:
        return False
示例#10
0
def altitude_diff(msg):
    """Decode the difference between GNSS and barometric altitude.

    Args:
        msg (str): 28 hexdigits string, TC=19

    Returns:
        int: Altitude difference in feet. Negative value indicates GNSS altitude
        below barometric altitude.

    """
    tc = common.typecode(msg)

    if tc != 19:
        raise RuntimeError(
            "%s: Not a airborne velocity message, expecting TC=19" % msg)

    msgbin = common.hex2bin(msg)
    sign = -1 if int(msgbin[80]) else 1
    value = common.bin2int(msgbin[81:88])

    if value == 0 or value == 127:
        return None
    else:
        return sign * (value - 1) * 25  # in ft.
示例#11
0
def trk50(msg):
    """True track angle, BDS 5,0 message

    Args:
        msg (str): 28 hexdigits string

    Returns:
        float: angle in degrees to true north (from 0 to 360)
    """
    d = common.hex2bin(common.data(msg))

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

    sign = int(d[12])  # 1 -> west
    value = common.bin2int(d[13:23])

    if sign:
        value = value - 1024

    trk = value * 90 / 512.0

    # convert from [-180, 180] to [0, 360]
    if trk < 0:
        trk = 360 + trk

    return round(trk, 3)
示例#12
0
文件: bds30.py 项目: wrobell/pyModeS
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
示例#13
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
示例#14
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
示例#15
0
def vertical_mode(msg):
    """Decode vertical mode.

    Value   Meaning
    -----   -----------------------
    1       "Acquiring" mode
    2       "Capturing" or "Maintaining" mode
    3       Reserved

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: Vertical mode

    """

    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 vertical mode, use vnav mode instead" % msg)

    vertical_mode = common.bin2int(mb[13:15])
    if vertical_mode == 0:
        return None

    return vertical_mode
示例#16
0
def is10(msg):
    """Check if a message is likely to be BDS code 1,0

    Args:
        msg (str): 28 hexdigits string

    Returns:
        bool: True or False
    """

    if common.allzeros(msg):
        return False

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

    # first 8 bits must be 0x10
    if d[0:8] != "00010000":
        return False

    # bit 10 to 14 are reserved
    if common.bin2int(d[9:14]) != 0:
        return False

    # overlay capability conflict
    if d[14] == "1" and common.bin2int(d[16:23]) < 5:
        return False
    if d[14] == "0" and common.bin2int(d[16:23]) > 4:
        return False

    return True
示例#17
0
def selected_altitude(msg):
    """Decode selected altitude.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        int: Selected altitude (ft)
        string: Source ('MCP/FCU' or 'FMS')

    """

    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 == 0:
        raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain selected altitude, use target altitude instead" % msg)

    alt = common.bin2int(mb[9:20])
    alt = None if alt == 0 else (alt - 1) * 32
    alt_source = "MCP/FCU" if int(mb[8]) == 0 else "FMS"

    return alt, alt_source
示例#18
0
文件: bds17.py 项目: wrobell/pyModeS
def is17(msg):
    """Check if a message is likely to be BDS code 1,7

    Args:
        msg (str): 28 hexdigits string

    Returns:
        bool: True or False
    """

    if common.allzeros(msg):
        return False

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

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

    caps = cap17(msg)

    # basic BDS codes for ADS-B shall be supported
    #   assuming ADS-B out is installed (2017EU/2020US mandate)
    # if not set(['BDS05', 'BDS06', 'BDS08', 'BDS09', 'BDS20']).issubset(caps):
    #     return False

    # at least you can respond who you are
    if "BDS20" not in caps:
        return False

    return True
示例#19
0
def hdg53(msg):
    """Magnetic heading, BDS 5,3 message

    Args:
        msg (str): 28 hexdigits string

    Returns:
        float: angle in degrees to true north (from 0 to 360)
    """
    d = common.hex2bin(common.data(msg))

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

    sign = int(d[1])  # 1 -> west
    value = common.bin2int(d[2:12])

    if sign:
        value = value - 1024

    hdg = value * 90.0 / 512.0  # degree

    # convert from [-180, 180] to [0, 360]
    if hdg < 0:
        hdg = 360 + hdg

    return round(hdg, 3)
示例#20
0
def selected_heading(msg):
    """Decode selected heading.

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

    Returns:
        float: Selected heading (degree)
    
    """

    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 == 0:
        raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain selected heading, use target angle instead" % msg)

    if int(mb[29]) == 0:
        hdg = None
    else:
        hdg_sign = int(mb[30])
        hdg = (hdg_sign+1) * common.bin2int(mb[31:39]) * (180/256)
        hdg = round(hdg, 2)

    return hdg
示例#21
0
def hdg60(msg):
    """Megnetic heading of aircraft

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

    Returns:
        float: heading in degrees to megnetic north (from 0 to 360)
    """
    d = common.hex2bin(common.data(msg))

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

    sign = int(d[1])  # 1 -> west
    value = common.bin2int(d[2:12])

    if sign:
        value = value - 1024

    hdg = value * 90 / 512.0  # degree

    # convert from [-180, 180] to [0, 360]
    if hdg < 0:
        hdg = 360 + hdg

    return round(hdg, 3)
示例#22
0
def baro_pressure_setting(msg):
    """Decode barometric pressure setting.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        float: Barometric pressure setting (millibars)

    """

    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 == 0:
        raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain barometric pressure setting" % msg)

    baro = common.bin2int(mb[20:29])
    baro = None if baro == 0 else 800 + (baro - 1) * 0.8
    baro = round(baro, 1)

    return baro
示例#23
0
文件: surv.py 项目: wrobell/pyModeS
def dr(msg):
    """Decode downlink request.

    Args:
        msg (str): 14 hexdigits string
    Returns:
        int, str: downlink request, description

    """
    msgbin = common.hex2bin(msg)
    dr = common.bin2int(msgbin[8:13])

    text = None

    if dr == 0:
        text = "no downlink request"
    elif dr == 1:
        text = "request to send Comm-B message"
    elif dr == 4:
        text = "Comm-B broadcast 1 available"
    elif dr == 5:
        text = "Comm-B broadcast 2 available"
    elif dr >= 16:
        text = "ELM downlink segments available: {}".format(dr - 15)

    return dr, text
示例#24
0
def approach_mode(msg) -> bool:
    """Decode approach mode.

    Args:
        msg (str): 28 hexdigits string

    Returns:
        bool: Approach mode engaged

    """

    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 == 0:
        raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain approach mode" % msg)

    if int(mb[46]) == 0:
        return None

    app_mode = True if int(mb[51]) == 1 else False

    return app_mode
示例#25
0
def nac_p(msg):
    """Calculate NACp, Navigation Accuracy Category - Position

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

    Returns:
        int or string: 95% horizontal accuracy bounds, Estimated Position Uncertainty
        int or string: 95% vertical accuracy bounds, Vertical Estimated Position Uncertainty
    """
    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:
        NACp = common.bin2int(msgbin[71:75])
    elif tc == 31:
        NACp = common.bin2int(msgbin[76:80])

    try:
        EPU = uncertainty.NACp[NACp]["EPU"]
        VEPU = uncertainty.NACp[NACp]["VEPU"]
    except KeyError:
        EPU, VEPU = uncertainty.NA, uncertainty.NA

    return EPU, VEPU
示例#26
0
def emergency_status(msg) -> int:
    """Decode aircraft emergency status.

    Value   Meaning
    -----   -----------------------
    0       No emergency
    1       General emergency
    2       Lifeguard/medical emergency
    3       Minimum fuel
    4       No communications
    5       Unlawful interference
    6       Downed aircraft
    7       Reserved

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

    Returns:
        int: Emergency status

    """

    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 emergency status" % msg)

    return common.bin2int(mb[53:56])
示例#27
0
def bds(msg):
    """Decode requested BDS register from selective (Roll Call) interrogation."""
    UF = uf(msg)
    msgbin = common.hex2bin(msg)
    msgbin_split = wrap(msgbin, 8)
    mbytes = list(map(common.bin2int, msgbin_split))

    if uf(msg) in {4, 5, 20, 21}:
        
        di = mbytes[1] & 0x7 # DI - Designator Identification
        RR = mbytes[1] >> 3 & 0x1F
        if RR > 15:
            BDS1 = RR - 16
            if di == 7:
                RRS = mbytes[2] & 0x0F
                BDS2 = RRS
            elif di == 3:
                RRS = ((mbytes[2] & 0x1) << 4) | ((mbytes[3] & 0xE0) >> 5)
                BDS2 = RRS
            else:
                BDS2 = 0 # for other values of DI, the BDS2 is assumed 0 (as per ICAO Annex 10 Vol IV)

            return str(BDS1) + str(BDS2)
        else:
            return None
    else:
        return None
示例#28
0
文件: adsb.py 项目: wrobell/pyModeS
def oe_flag(msg):
    """Check the odd/even flag. Bit 54, 0 for even, 1 for odd.
    Args:
        msg (str): 28 hexdigits string
    Returns:
        int: 0 or 1, for even or odd frame
    """
    msgbin = common.hex2bin(msg)
    return int(msgbin[53])
示例#29
0
def is60(msg):
    """Check if a message is likely to be BDS code 6,0

    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, 13, 24, 35, 46

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

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

    if common.wrongstatus(d, 24, 25, 34):
        return False

    if common.wrongstatus(d, 35, 36, 45):
        return False

    if common.wrongstatus(d, 46, 47, 56):
        return False

    ias = ias60(msg)
    if ias is not None and ias > 500:
        return False

    mach = mach60(msg)
    if mach is not None and mach > 1:
        return False

    vr_baro = vr60baro(msg)
    if vr_baro is not None and abs(vr_baro) > 6000:
        return False

    vr_ins = vr60ins(msg)
    if vr_ins is not None and abs(vr_ins) > 6000:
        return False

    # additional check knowing altitude
    if (mach is not None) and (ias is not None) and (common.df(msg) == 20):
        alt = common.altcode(msg)
        if alt is not None:
            ias_ = aero.mach2cas(mach, alt * aero.ft) / aero.kts
            if abs(ias - ias_) > 20:
                return False

    return True
示例#30
0
文件: adsb.py 项目: stinby/pyModeS
def oe_flag(msg):
    """Check the odd/even flag. Bit 54, 0 for even, 1 for odd.
    Args:
        msg (string): 28 bytes hexadecimal message string
    Returns:
        int: 0 or 1, for even or odd frame
    """
    msgbin = common.hex2bin(msg)
    return int(msgbin[53])