Exemplo n.º 1
0
def adsb_decode_all(n=None):
    print("===== Decode ADS-B sample data=====")
    import csv
    f = open('tests/data/sample_data_adsb.csv', 'rt')

    msg0 = None
    msg1 = None

    for i, r in enumerate(csv.reader(f)):
        if n and i > n:
            break

        ts = r[0]
        m = r[1]
        icao = adsb.icao(m)
        tc = adsb.typecode(m)
        if 1 <= tc <= 4:
            print(ts, m, icao, tc, adsb.category(m), adsb.callsign(m))
        if tc == 19:
            print(ts, m, icao, tc, adsb.velocity(m))
        if 5 <= tc <= 18:
            if adsb.oe_flag(m):
                msg1 = m
                t1 = ts
            else:
                msg0 = m
                t0 = ts

            if msg0 and msg1:
                pos = adsb.position(msg0, msg1, t0, t1)
                alt = adsb.altitude(m)
                print(ts, m, icao, tc, pos, alt)
Exemplo n.º 2
0
def adsb_decode_all(n=None):
    print "===== Decode all ADS-B sample data====="
    import csv
    f = open('adsb.csv', 'rt')

    msg0 = None
    msg1 = None

    for i, r in enumerate(csv.reader(f)):
        if n and i > n:
            break

        ts = r[0]
        m = r[1]
        icao = adsb.icao(m)
        tc = adsb.typecode(m)
        if 1 <= tc <= 4:
            print ts, m, icao, tc, adsb.category(m), adsb.callsign(m)
        if tc == 19:
            print ts, m, icao, tc, adsb.velocity(m)
        if 5 <= tc <= 18:
            if adsb.oe_flag(m):
                msg1 = m
                t1 = ts
            else:
                msg0 = m
                t0 = ts

            if msg0 and msg1:
                pos = adsb.position(msg0, msg1, t0, t1)
                alt = adsb.altitude(m)
                print ts, m, icao, tc, pos, alt
Exemplo n.º 3
0
def test_adsb_category():
    assert adsb.category("8D406B902015A678D4D220AA4BDA") == 5
Exemplo n.º 4
0
def test_adsb_category():
    assert adsb.category("8D406B902015A678D4D220AA4BDA") == 0
Exemplo n.º 5
0
  def _parse(self, msg_ascii):
    if not msg_ascii or msg_ascii[0] != '*':
      raise ValueError

    msg_hex = msg_ascii[1:].split(';', 1)[0]

    try:
      icao = adsb.icao(msg_hex).lower()
      downlink_format = df(msg_hex)
      type_code = adsb.typecode(msg_hex)
    except:
      raise ValueError

    # version 0 is assumed, so populate it on initialisation
    ac_data = self.positions.get(icao, {"version": 0})

    if downlink_format == 17 or downlink_format == 18:
      # An aircraft airborne position message has downlink format 17 (or 18) with
      # type code from 9 to 18 (baro altitude) or 20 to 22 (GNSS altitude)
      # ref https://mode-s.org/decode/adsb/airborne-position.html
      if ac_data.get("version", None) == 1 and ac_data.get("nic_s", None):
        ac_data["nic"] = adsb.nic_v1(msg_hex, ac_data["nic_s"])

      if (type_code >= 1 and type_code <= 4):
        # Slightly normalise the callsign - it's supposed to only be [0-9A-Z]
        # with space padding. PyModeS uses _ padding, which I think is an older
        # version of the spec.
        ac_data["callsign"] = adsb.callsign(msg_hex).upper().replace("_", " ")[:8]
        ac_data["emitter_category"] = adsb.category(msg_hex)
      elif (type_code >= 9 and type_code <= 18) or (type_code >= 20 and type_code <= 22):
        nuc_p = None
        if ac_data.get("version", None) == 0:
          # In ADSB version 0, the type code encodes the nuc_p (navigational
          # uncertianty category - position) value via this magic lookup table
          nuc_p_lookup = {
            9: 9,
            10: 8,
            11: 7,
            12: 6,
            13: 5,
            14: 4,
            15: 3,
            16: 2,
            17: 1,
            18: 0,
            20: 9,
            21: 8,
            22: 0,
          }
          ac_data["nuc_p"] = nuc_p_lookup.get(type_code, None)

        elif ac_data.get("version", None) == 2:
          ac_data["nic_b"] = adsb.nic_b(msg_hex)

        if ac_data.get("version", None) == 2 and "nic_a" in ac_data.keys() and "nic_c" in ac_data.keys():
          nic_a = ac_data["nic_a"]
          nic_c = ac_data["nic_c"]
          ac_data["nic"] = adsb.nic_v2(msg_hex, nic_a, nic_c)

        # Aircraft position
        if not self.gps.is_fresh():
          #print("aircraft: not updating {0} df={1} tc={2} as my GPS position is unknown ({3})".format(icao, downlink_format, type_code, msg_hex))
          raise ValueError

        # Use the known location of the receiver to calculate the aircraft position
        # from one messsage
        try:
          my_latitude, my_longitude = self.gps.position()
        except NoFixError:
          # For testing
          my_latitude, my_longitude = (51.519559, -0.114227)
          # a rare race condition
          #raise ValueError

        ac_lat, ac_lon = adsb.position_with_ref(msg_hex, my_latitude, my_longitude)
        #print("aircraft: update {0} df={1} tc={2} {3}, {4} ({5})".format(icao, downlink_format, type_code, ac_lat, ac_lon, msg_hex))

        ac_data["lat"] = ac_lat
        ac_data["lon"] = ac_lon

      elif type_code == 19:
        # From the docs: returns speed (kt) ground track or heading (degree),
        # rate of climb/descent (ft/min), speed type (‘GS’ for ground speed,
        # ‘AS’ for airspeed), direction source (‘true_north’ for ground track /
        # true north as refrence, ‘mag_north’ for magnetic north as reference),
        # rate of climb/descent source (‘Baro’ for barometer, ‘GNSS’ for GNSS
        # constellation).
        if ac_data.get("version", None) == 1 or ac_data.get("version", None) == 2:
          ac_data["nac_v"] = adsb.nac_v(msg_hex)

        try:
          (speed, track, climb, speed_source, track_source, climb_source) = adsb.velocity(msg_hex, rtn_sources=True)
          ac_data["speed_h"] = speed
          ac_data["track"] = track
          ac_data["speed_v"] = climb
          ac_data["speed_h_source"] = speed_source
          ac_data["track_source"] = track_source
          ac_data["speed_v_source"] = climb_source
        except TypeError:
          # adsb.velocity can return None
          raise ValueError

      elif type_code == 31:
        # Operational status
        version = adsb.version(msg_hex)
        nic_s = adsb.nic_s(msg_hex)

        # v0 nuc_p is determined by type_code above
        if version == 1:
          try:
            # Is this the right place for nucp? The docs say yes, but one error
            # I've received says 8d3c5ee6f81300000039283c21cf: Not a surface
            # position message (5<TC<8), airborne position message (8<TC<19),
            # or airborne position with GNSS height (20<TC<22)
            nuc_p = adsb.nuc_p(msg_hex)
            nuc_v = adsb.nuc_v(msg_hex)
          except RuntimeError as e:
            print("aircraft: error parsing v1 NUC: {}".format(e))
            raise ValueError

          ac_data["nic_s"] = nic_s
          ac_data["nuc_p"] = nuc_p
          ac_data["nuc_v"] = nuc_v
          ac_data["nac_p"] = adsb.nac_p(msg_hex)
          ac_data["sil"] = adsb.sil(msg_hex, version)
        elif version == 2:
          ac_data["nac_p"] = adsb.nac_p(msg_hex)
          (nic_a, nic_c) = adsb.nic_a_c(msg_hex)
          ac_data["nic_a"] = nic_a
          ac_data["nic_c"] = nic_c
          ac_data["sil"] = adsb.sil(msg_hex, version)

        ac_data["version"] = version
        ac_data["nic_s"] = nic_s
      else:
        raise ValueError

    elif downlink_format == 4 or downlink_format == 20:
      altitude = adsb_common.altcode(msg_hex)
      ac_data["altitude"] = altitude
    else:
      # unsupported message
      raise ValueError

    ac_data["updated"] = datetime.now()
    self.positions[icao] = ac_data