Пример #1
0
def callsign(msg):
    """Aircraft callsign
    Args:
        msg (string): 28 bytes hexadecimal message string
    Returns:
        string: callsign
    """

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

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

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

    # clean string, remove spaces and marks, if any.
    # cs = cs.replace('_', '')
    cs = cs.replace('#', '')
    return cs
Пример #2
0
def isBDS60(msg):
    """Check if a message is likely to be BDS code 6,0
    Args:
        msg (String): 28 bytes hexadecimal message string
    Returns:
        bool: True or False
    """
    # status bit 1, 13, 24, 35, 46
    d = util.hex2bin(data(msg))

    result = True

    result = result & checkbits(d, 1, 2, 12) & checkbits(d, 13, 14, 23) \
        & checkbits(d, 24, 25, 34) & checkbits(d, 35, 36, 45) \
        & checkbits(d, 46, 47, 56)

    if not (1 < ias(msg) < 500):
        result &= False

    if not (0.0 < mach(msg) < 1.0):
        result &= False

    if abs(baro_vr(msg)) > 5000:
        result &= False

    if abs(ins_vr(msg)) > 5000:
        result &= False

    return result
Пример #3
0
def isBDS50(msg):
    """Check if a message is likely to be BDS code 5,0
    Args:
        msg (String): 28 bytes hexadecimal message string
    Returns:
        bool: True or False
    """
    # status bit 1, 12, 24, 35, 46
    d = util.hex2bin(data(msg))

    result = True

    result = result & checkbits(d, 1, 3, 11) & checkbits(d, 12, 13, 23) \
        & checkbits(d, 24, 25, 34) & checkbits(d, 35, 36, 45) \
        & checkbits(d, 46, 47, 56)

    if d[2:11] == "000000000":
        result &= True
    else:
        if abs(roll(msg)) > 30:
            result &= False

    if gs(msg) > 500:
        result &= False

    if tas(msg) > 500:
        result &= False

    if abs(tas(msg) - gs(msg)) > 100:
        result &= False

    return result
Пример #4
0
def test_crc():
    # crc decoder
    checksum = util.crc("8D406B902015A678D4D220AA4BDA")
    assert checksum == "000000000000000000000000"

    # crc encoder
    parity = util.crc("8D406B902015A678D4D220AA4BDA", encode=True)
    assert util.hex2bin("AA4BDA") == parity
Пример #5
0
def test_crc():
    # crc decoder
    checksum = util.crc("8D406B902015A678D4D220AA4BDA")
    assert checksum == "000000000000000000000000"

    # crc encoder
    parity = util.crc("8D406B902015A678D4D220AA4BDA", encode=True)
    assert util.hex2bin("AA4BDA") == parity
Пример #6
0
def typecode(msg):
    """Type code of ADS-B message
    Args:
        msg (string): 28 bytes hexadecimal message string
    Returns:
        int: type code number
    """
    msgbin = util.hex2bin(msg)
    return util.bin2int(msgbin[32:37])
Пример #7
0
def ias(msg):
    """Indicated airspeed
    Args:
        msg (String): 28 bytes hexadecimal message (BDS60) string
    Returns:
        int: indicated airspeed in knots
    """
    d = util.hex2bin(data(msg))
    ias = util.bin2int(d[13:23])    # kts
    return ias
Пример #8
0
def tas(msg):
    """Aircraft true airspeed
    Args:
        msg (String): 28 bytes hexadecimal message (BDS50) string
    Returns:
        int: true airspeed in knots
    """
    d = util.hex2bin(data(msg))
    spd = util.bin2int(d[46:56]) * 2   # kts
    return spd
Пример #9
0
def gs(msg):
    """Aircraft ground speed
    Args:
        msg (String): 28 bytes hexadecimal message (BDS50) string
    Returns:
        int: ground speed in knots
    """
    d = util.hex2bin(data(msg))
    spd = util.bin2int(d[24:34]) * 2    # kts
    return spd
Пример #10
0
def pbaro(msg):
    """Barometric pressure setting
    Args:
        msg (String): 28 bytes hexadecimal message (BDS40) string
    Returns:
        float: pressure in millibar
    """
    d = util.hex2bin(data(msg))
    p = util.bin2int(d[27:39]) * 0.1 + 800    # millibar
    return p
Пример #11
0
def mach(msg):
    """Aircraft MACH number
    Args:
        msg (String): 28 bytes hexadecimal message (BDS60) string
    Returns:
        float: MACH number
    """
    d = util.hex2bin(data(msg))
    mach = util.bin2int(d[24:34]) * 2.048 / 512.0
    return round(mach, 3)
Пример #12
0
def alt_fms(msg):
    """Selected altitude, FMS
    Args:
        msg (String): 28 bytes hexadecimal message (BDS40) string
    Returns:
        int: altitude in feet
    """
    d = util.hex2bin(data(msg))
    alt = util.bin2int(d[14:26]) * 16    # ft
    return alt
Пример #13
0
def track(msg):
    """True track angle
    Args:
        msg (String): 28 bytes hexadecimal message (BDS50) string
    Returns:
        float: angle in degrees to true north (from 0 to 360)
    """
    d = util.hex2bin(data(msg))
    sign = int(d[12])   # 1 -> west
    value = util.bin2int(d[13:23]) * 90 / 512.0    # degree
    angle = 360 - value if sign else value
    return round(angle, 1)
Пример #14
0
def rtrack(msg):
    """Track angle rate
    Args:
        msg (String): 28 bytes hexadecimal message (BDS50) string
    Returns:
        float: angle rate in degrees/second
    """
    d = util.hex2bin(data(msg))
    sign = int(d[35])    # 1 -> minus
    value = util.bin2int(d[36:45]) * 8 / 256.0    # degree / sec
    angle = -1 * value if sign else value
    return round(angle, 3)
Пример #15
0
def heading(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 = util.hex2bin(data(msg))
    sign = int(d[1])    # 1 -> west
    value = util.bin2int(d[2:12]) * 90 / 512.0  # degree
    hdg = 360 - value if sign else value
    return round(hdg, 1)
Пример #16
0
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
    """
    if typecode(msg) < 5 or typecode(msg) > 18:
        raise RuntimeError("%s: Not a position message" % msg)

    msgbin = util.hex2bin(msg)
    return int(msgbin[53])
Пример #17
0
def cprlon(msg):
    """CPR encoded longitude
    Args:
        msg (string): 28 bytes hexadecimal message string
    Returns:
        int: encoded longitude
    """
    if typecode(msg) < 5 or typecode(msg) > 18:
        raise RuntimeError("%s: Not a position message" % msg)

    msgbin = util.hex2bin(msg)
    return util.bin2int(msgbin[71:88])
Пример #18
0
def baro_vr(msg):
    """Vertical rate from barometric measurement
    Args:
        msg (String): 28 bytes hexadecimal message (BDS60) string
    Returns:
        int: vertical rate in feet/minutes
    """
    d = util.hex2bin(data(msg))
    sign = d[35]    # 1 -> minus
    value = util.bin2int(d[36:45]) * 32   # feet/min
    roc = -1*value if sign else value
    return roc
Пример #19
0
def ins_vr(msg):
    """Vertical rate messured by onbard equiments (IRS, AHRS)
    Args:
        msg (String): 28 bytes hexadecimal message (BDS60) string
    Returns:
        int: vertical rate in feet/minutes
    """
    d = util.hex2bin(data(msg))
    sign = d[46]    # 1 -> minus
    value = util.bin2int(d[47:56]) * 32   # feet/min
    roc = -1*value if sign else value
    return roc
Пример #20
0
def category(msg):
    """Aircraft category number
    Args:
        msg (string): 28 bytes hexadecimal message string
    Returns:
        int: category number
    """

    if typecode(msg) < 1 or typecode(msg) > 4:
        raise RuntimeError("%s: Not a identification message" % msg)
    msgbin = util.hex2bin(msg)
    return util.bin2int(msgbin[5:8])
Пример #21
0
def roll(msg):
    """Aircraft roll angle
    Args:
        msg (String): 28 bytes hexadecimal message (BDS50) string
    Returns:
        float: angle in degrees,
               negative->left wing down, positive->right wing down
    """
    d = util.hex2bin(data(msg))
    sign = int(d[1])    # 1 -> left wing down
    value = util.bin2int(d[2:11]) * 45 / 256.0    # degree
    angle = -1 * value if sign else value
    return round(angle, 1)
Пример #22
0
def velocity(msg):
    """Calculate the speed, heading, and vertical rate
    Args:
        msg (string): 28 bytes hexadecimal message string
    Returns:
        (int, float, int, string): speed (kt), heading (degree),
            rate of climb/descend (ft/min), and speed type
            ('GS' for ground speed, 'AS' for airspeed)
    """

    if typecode(msg) != 19:
        raise RuntimeError("%s: Not a airborne velocity message" % msg)

    msgbin = util.hex2bin(msg)

    subtype = util.bin2int(msgbin[37:40])

    if subtype in (1, 2):
        v_ew_sign = util.bin2int(msgbin[45])
        v_ew = util.bin2int(msgbin[46:56]) - 1       # east-west velocity

        v_ns_sign = util.bin2int(msgbin[56])
        v_ns = util.bin2int(msgbin[57:67]) - 1       # north-south velocity

        v_we = -1*v_ew if v_ew_sign else v_ew
        v_sn = -1*v_ns if v_ns_sign else v_ns

        spd = math.sqrt(v_sn*v_sn + v_we*v_we)  # unit in kts

        hdg = math.atan2(v_we, v_sn)
        hdg = math.degrees(hdg)                 # convert to degrees
        hdg = hdg if hdg >= 0 else hdg + 360    # no negative val

        tag = 'GS'

    else:
        hdg = util.bin2int(msgbin[46:56]) / 1024.0 * 360.0
        spd = util.bin2int(msgbin[57:67])

        tag = 'AS'

    vr_sign = util.bin2int(msgbin[68])
    vr = util.bin2int(msgbin[68:77])             # vertical rate
    rocd = -1*vr if vr_sign else vr         # rate of climb/descend

    return int(spd), round(hdg, 1), int(rocd), tag
Пример #23
0
def altitude(msg):
    """Decode aircraft altitude
    Args:
        msg (string): 28 bytes hexadecimal message string
    Returns:
        int: altitude in feet
    """
    if typecode(msg) < 9 or typecode(msg) > 18:
        raise RuntimeError("%s: Not a position message" % msg)

    msgbin = util.hex2bin(msg)
    q = msgbin[47]
    if q:
        n = util.bin2int(msgbin[40:47]+msgbin[48:52])
        alt = n * 25 - 1000
        return alt
    else:
        return None
Пример #24
0
def nic(msg):
    """Calculate NIC, navigation integrity category
    Args:
        msg (string): 28 bytes hexadecimal message string
    Returns:
        int: NIC number (from 0 to 11), -1 if not applicable
    """
    if typecode(msg) < 9 or typecode(msg) > 18:
        raise RuntimeError("%s: Not a airborne position message" % msg)

    msgbin = util.hex2bin(msg)
    tc = typecode(msg)
    nic_sup_b = util.bin2int(msgbin[39])

    if tc in [0, 18, 22]:
        nic = 0
    elif tc == 17:
        nic = 1
    elif tc == 16:
        if nic_sup_b:
            nic = 3
        else:
            nic = 2
    elif tc == 15:
        nic = 4
    elif tc == 14:
        nic = 5
    elif tc == 13:
        nic = 6
    elif tc == 12:
        nic = 7
    elif tc == 11:
        if nic_sup_b:
            nic = 9
        else:
            nic = 8
    elif tc in [10, 21]:
        nic = 10
    elif tc in [9, 20]:
        nic = 11
    else:
        nic = -1
    return nic
Пример #25
0
def isBDS20(msg):
    """Check if a message is likely to be BDS code 2,0
    Args:
        msg (String): 28 bytes hexadecimal message string
    Returns:
        bool: True or False
    """
    # status bit 1, 14, and 27
    d = util.hex2bin(data(msg))

    result = True

    if util.bin2int(d[0:4]) != 2 or util.bin2int(d[4:8]) != 0:
        result &= False

    cs = callsign(msg)

    if '#' in cs:
        result &= False

    return result
Пример #26
0
def callsign(msg):
    """Aircraft callsign
    Args:
        msg (String): 28 bytes hexadecimal message (BDS40) string
    Returns:
        string: callsign, max. 8 chars
    """
    chars = '#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######'

    d = util.hex2bin(data(msg))

    cs = ''
    cs += chars[util.bin2int(d[8:14])]
    cs += chars[util.bin2int(d[14:20])]
    cs += chars[util.bin2int(d[20:26])]
    cs += chars[util.bin2int(d[26:32])]
    cs += chars[util.bin2int(d[32:38])]
    cs += chars[util.bin2int(d[38:44])]
    cs += chars[util.bin2int(d[44:50])]
    cs += chars[util.bin2int(d[50:56])]

    return cs
Пример #27
0
def isBDS40(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
    """
    # status bit 1, 14, and 27
    d = util.hex2bin(data(msg))

    result = True

    result = result & checkbits(d, 1, 2, 13) \
        & checkbits(d, 14, 15, 26) & checkbits(d, 27, 28, 39)

    # bits 40-47 and 52-53 shall all be zero
    if util.bin2int(d[39:47]) != 0:
        result &= False

    if util.bin2int(d[51:53]) != 0:
        result &= False

    return result
Пример #28
0
def test_crc_encode():
    parity = util.crc("8D406B902015A678D4D220AA4BDA", encode=True)
    assert util.hex2bin("AA4BDA") == parity
Пример #29
0
def test_hex2bin():
    assert util.hex2bin('6E406B') == "011011100100000001101011"
Пример #30
0
def position(msg0, msg1, t0, t1):
    """Decode position from the combination of even and odd position message
        131072 is 2^17, since CPR lat and lon are 17 bits each.
    Args:
        msg0 (string): even message (28 bytes hexadecimal string)
        msg1 (string): odd message (28 bytes hexadecimal string)
        t0 (int): timestamps for the even message
        t1 (int): timestamps for the odd message
    Returns:
        (float, float): (latitude, longitude) of the aircraft
    """
    if typecode(msg0) < 5 or typecode(msg0) > 18:
        raise RuntimeError("%s: Not a position message" % msg0)

    if typecode(msg1) < 5 or typecode(msg1) > 18:
        raise RuntimeError("%s: Not a position message" % msg1)

    msgbin0 = util.hex2bin(msg0)
    msgbin1 = util.hex2bin(msg1)

    cprlat_even = util.bin2int(msgbin0[54:71]) / 131072.0
    cprlon_even = util.bin2int(msgbin0[71:88]) / 131072.0
    cprlat_odd = util.bin2int(msgbin1[54:71]) / 131072.0
    cprlon_odd = util.bin2int(msgbin1[71:88]) / 131072.0

    air_d_lat_even = 360.0 / 60
    air_d_lat_odd = 360.0 / 59

    # compute latitude index 'j'
    j = int(math.floor(59 * cprlat_even - 60 * cprlat_odd + 0.5))

    lat_even = float(air_d_lat_even * (j % 60 + cprlat_even))
    lat_odd = float(air_d_lat_odd * (j % 59 + cprlat_odd))

    if lat_even >= 270:
        lat_even = lat_even - 360

    if lat_odd >= 270:
        lat_odd = lat_odd - 360

    # check if both are in the same latidude zone, exit if not
    if _cprNL(lat_even) != _cprNL(lat_odd):
        return None

    # compute ni, longitude index m, and longitude
    if (t0 > t1):
        ni = _cprN(lat_even, 0)
        m = math.floor(cprlon_even * (_cprNL(lat_even)-1) -
                       cprlon_odd * _cprNL(lat_even) + 0.5)
        lon = (360.0 / ni) * (m % ni + cprlon_even)
        lat = lat_even
    else:
        ni = _cprN(lat_odd, 1)
        m = math.floor(cprlon_even * (_cprNL(lat_odd)-1) -
                       cprlon_odd * _cprNL(lat_odd) + 0.5)
        lon = (360.0 / ni) * (m % ni + cprlon_odd)
        lat = lat_odd

    if lon > 180:
        lon = lon - 360

    return round(lat, 5), round(lon, 5)
Пример #31
0
def test_crc_encode():
    parity = util.crc("8D406B902015A678D4D220AA4BDA", encode=True)
    assert util.hex2bin("AA4BDA") == parity
Пример #32
0
def test_hex2bin():
    assert util.hex2bin('6E406B') == "011011100100000001101011"