Пример #1
0
    def output(self, msg):
        try:
            msgtype = msg.data["df"]
            if msgtype == 17: #ADS-B report
                icao24 = msg.data["aa"]
                bdsreg = msg.data["me"].get_type()
                if bdsreg == 0x08: #ident packet
                    (ident, actype) = air_modes.parseBDS08(msg.data)
                    #select model based on actype
                    self.callsigns[icao24] = [ident, actype]

                elif bdsreg == 0x06: #BDS0,6 pos
                    [ground_track, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS06(msg.data, self._cpr)
                    self.positions[icao24] = [decoded_lat, decoded_lon, 0]
                    self.update(icao24)

                elif bdsreg == 0x05: #BDS0,5 pos
                    [altitude, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS05(msg.data, self._cpr)
                    self.positions[icao24] = [decoded_lat, decoded_lon, altitude]
                    self.update(icao24)

                elif bdsreg == 0x09: #velocity
                    subtype = msg.data["bds09"].get_type()
                    if subtype == 0:
                      [velocity, heading, vert_spd, turnrate] = air_modes.parseBDS09_0(msg.data)
                    elif subtype == 1:
                      [velocity, heading, vert_spd] = air_modes.parseBDS09_1(msg.data)
                      turnrate = 0
                    else:
                        return

                    self.velocities[icao24] = [velocity, heading, vert_spd, turnrate]

        except ADSBError:
            pass
Пример #2
0
  def sql17(self, data):
    nw = datetime.datetime.utcnow()
    icao24 = data["aa"]
    bdsreg = data["me"].get_type()
    #self["bds%.2i" % bdsreg] = icao24 #publish under "bds08", "bds06", etc.
    #nw = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')
    
    if bdsreg == 0x08:
      (msg, typename) = air_modes.parseBDS08(data)
      return "INSERT OR REPLACE INTO ident (icao, ident, type) VALUES (?, ?, ?)", (icao24, msg, typename)
    elif bdsreg == 0x06:
      [ground_track, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS06(data, self._cpr)
      altitude = 0
      if decoded_lat is None: #no unambiguously valid position available
        raise CPRNoPositionError
      else:
        return "INSERT INTO positions (icao, seen, alt, lat, lon) VALUES (?, ?, ?, ?, ?)", (icao24, nw, altitude, decoded_lat, decoded_lon)
    elif bdsreg == 0x05:
      [altitude, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS05(data, self._cpr)
      if decoded_lat is None: #no unambiguously valid position available
        raise CPRNoPositionError
      else:
        return "INSERT INTO positions (icao, seen, alt, lat, lon) VALUES (?, ?, ?, ?, ?)", (icao24, nw, altitude, decoded_lat, decoded_lon)
    elif bdsreg == 0x09:
      subtype = data["bds09"].get_type()
      if subtype == 0:
        [velocity, heading, vert_spd, turnrate] = air_modes.parseBDS09_0(data)
        return "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (?, ?, ?, ?, ?)", (icao24, nw, velocity, heading, vert_spd)
      elif subtype == 1:
        [velocity, heading, vert_spd] = air_modes.parseBDS09_1(data)
        return "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (?, ?, ?, ?, ?)", (icao24, nw, velocity, heading, vert_spd)
      else:
        raise NoHandlerError

    return None, None
Пример #3
0
  def sql17(self, data):
    icao24 = data["aa"]
    bdsreg = data["me"].get_type()
    #self["bds%.2i" % bdsreg] = icao24 #publish under "bds08", "bds06", etc.

    if bdsreg == 0x08:
      (msg, typename) = air_modes.parseBDS08(data)
      return "INSERT OR REPLACE INTO ident (icao, ident, type) VALUES (" + "%i" % icao24 + ", '" + msg + "', '" + typename + "')"
    elif bdsreg == 0x06:
      [ground_track, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS06(data, self._cpr)
      altitude = 0
      if decoded_lat is None: #no unambiguously valid position available
        raise CPRNoPositionError
      else:
        return "INSERT INTO positions (icao, seen, alt, lat, lon) VALUES (" + "%i" % icao24 + ", datetime('now'), " + str(altitude) + ", " + "%.6f" % decoded_lat + ", " + "%.6f" % decoded_lon + ")"
    elif bdsreg == 0x05:
      [altitude, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS05(data, self._cpr)
      if decoded_lat is None: #no unambiguously valid position available
        raise CPRNoPositionError
      else:
        return "INSERT INTO positions (icao, seen, alt, lat, lon) VALUES (" + "%i" % icao24 + ", datetime('now'), " + str(altitude) + ", " + "%.6f" % decoded_lat + ", " + "%.6f" % decoded_lon + ")"
    elif bdsreg == 0x09:
      subtype = data["bds09"].get_type()
      if subtype == 0:
        [velocity, heading, vert_spd, turnrate] = air_modes.parseBDS09_0(data)
        return "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (" + "%i" % icao24 + ", datetime('now'), " + "%.0f" % velocity + ", " + "%.0f" % heading + ", " + "%.0f" % vert_spd + ")"
      elif subtype == 1:
        [velocity, heading, vert_spd] = air_modes.parseBDS09_1(data)
        return "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (" + "%i" % icao24 + ", datetime('now'), " + "%.0f" % velocity + ", " + "%.0f" % heading + ", " + "%.0f" % vert_spd + ")"
      else:
        raise NoHandlerError
Пример #4
0
    def output(self, msg):
        try:
            msgtype = msg.data["df"]
            if msgtype == 17: #ADS-B report
                icao24 = msg.data["aa"]
                bdsreg = msg.data["me"].get_type()
                if bdsreg == 0x08: #ident packet
                    (ident, actype) = air_modes.parseBDS08(msg.data)
                    #select model based on actype
                    self.callsigns[icao24] = [ident, actype]

                elif bdsreg == 0x06: #BDS0,6 pos
                    [ground_track, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS06(msg.data, self._cpr)
                    self.positions[icao24] = [decoded_lat, decoded_lon, 0]
                    self.update(icao24)

                elif bdsreg == 0x05: #BDS0,5 pos
                    [altitude, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS05(msg.data, self._cpr)
                    self.positions[icao24] = [decoded_lat, decoded_lon, altitude]
                    self.update(icao24)

                elif bdsreg == 0x09: #velocity
                    subtype = msg.data["bds09"].get_type()
                    if subtype == 0:
                      [velocity, heading, vert_spd, turnrate] = air_modes.parseBDS09_0(msg.data)
                    elif subtype == 1:
                      [velocity, heading, vert_spd] = air_modes.parseBDS09_1(msg.data)
                      turnrate = 0
                    else:
                        return

                    self.velocities[icao24] = [velocity, heading, vert_spd, turnrate]

        except ADSBError:
            pass
Пример #5
0
    def output(self, msg):
        try:
            msgtype = msg.data["df"]
            now = time.time()
            newrow = {"rssi": msg.rssi, "seen": now}
            if msgtype in [0, 4, 20]:
                newrow["altitude"] = air_modes.altitude.decode_alt(
                    msg.data["ac"], True)
                newrow["icao"] = msg.ecc
                self.model.addRecord(newrow)

            elif msgtype == 17:
                icao = msg.data["aa"]
                newrow["icao"] = icao
                subtype = msg.data["ftc"]
                if subtype == 4:
                    (ident, actype) = air_modes.parseBDS08(msg.data)
                    newrow["ident"] = ident
                    newrow["type"] = actype
                elif 5 <= subtype <= 8:
                    (ground_track, decoded_lat, decoded_lon, rnge,
                     bearing) = air_modes.parseBDS06(msg.data, self._cpr)
                    newrow["heading"] = ground_track
                    newrow["latitude"] = decoded_lat
                    newrow["longitude"] = decoded_lon
                    newrow["altitude"] = 0
                    if rnge is not None:
                        newrow["range"] = rnge
                        newrow["bearing"] = bearing
                elif 9 <= subtype <= 18:
                    (altitude, decoded_lat, decoded_lon, rnge,
                     bearing) = air_modes.parseBDS05(msg.data, self._cpr)
                    newrow["altitude"] = altitude
                    newrow["latitude"] = decoded_lat
                    newrow["longitude"] = decoded_lon
                    if rnge is not None:
                        newrow["range"] = rnge
                        newrow["bearing"] = bearing
                elif subtype == 19:
                    subsubtype = msg.data["sub"]
                    velocity = None
                    heading = None
                    vert_spd = None
                    if subsubtype == 0:
                        (velocity, heading,
                         vert_spd) = air_modes.parseBDS09_0(msg.data)
                    elif 1 <= subsubtype <= 2:
                        (velocity, heading,
                         vert_spd) = air_modes.parseBDS09_1(msg.data)
                    newrow["speed"] = velocity
                    newrow["heading"] = heading
                    newrow["vertical"] = vert_spd

                self.model.addRecord(newrow)

        except ADSBError:
            return
Пример #6
0
    def output(self, msg):
        try:
            msgtype = msg.data["df"]
            now = time.time()
            newrow = {"rssi": msg.rssi, "seen": now}
            if msgtype in [0, 4, 20]:
                newrow["altitude"] = air_modes.altitude.decode_alt(msg.data["ac"], True)
                newrow["icao"] = msg.ecc
                self.model.addRecord(newrow)
            
            elif msgtype == 17:
                icao = msg.data["aa"]
                newrow["icao"] = icao
                subtype = msg.data["ftc"]
                if subtype == 4:
                    (ident, actype) = air_modes.parseBDS08(msg.data)
                    newrow["ident"] = ident
                    newrow["type"] = actype
                elif 5 <= subtype <= 8:
                    (ground_track, decoded_lat, decoded_lon, rnge, bearing) = air_modes.parseBDS06(msg.data, self._cpr)
                    newrow["heading"] = ground_track
                    newrow["latitude"] = decoded_lat
                    newrow["longitude"] = decoded_lon
                    newrow["altitude"] = 0
                    if rnge is not None:
                        newrow["range"] = rnge
                        newrow["bearing"] = bearing
                elif 9 <= subtype <= 18:
                    (altitude, decoded_lat, decoded_lon, rnge, bearing) = air_modes.parseBDS05(msg.data, self._cpr)
                    newrow["altitude"] = altitude
                    newrow["latitude"] = decoded_lat
                    newrow["longitude"] = decoded_lon
                    if rnge is not None:
                        newrow["range"] = rnge
                        newrow["bearing"] = bearing
                elif subtype == 19:
                    subsubtype = msg.data["sub"]
                    velocity = None
                    heading = None
                    vert_spd = None
                    if subsubtype == 0:
                        (velocity, heading, vert_spd) = air_modes.parseBDS09_0(msg.data)
                    elif 1 <= subsubtype <= 2:
                        (velocity, heading, vert_spd) = air_modes.parseBDS09_1(msg.data)
                    newrow["speed"] = velocity
                    newrow["heading"] = heading
                    newrow["vertical"] = vert_spd
    
                self.model.addRecord(newrow)

        except ADSBError:
            return
Пример #7
0
  def handle17(self, msg):
    icao24 = msg.data["aa"]
    bdsreg = msg.data["me"].get_type()

    retstr = output_print.prefix(msg)
    try:
        if bdsreg == 0x08:
          (ident, typestring) = air_modes.parseBDS08(msg.data)
          retstr += "Type 17 BDS0,8 (ident) from %x type %s ident %s" % (icao24, typestring, ident)

        elif bdsreg == 0x06:
          [ground_track, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS06(msg.data, self._cpr)
          retstr += "Type 17 BDS0,6 (surface report) from %x at (%.6f, %.6f) ground track %i" % (icao24, decoded_lat, decoded_lon, ground_track)
          if rnge is not None and bearing is not None:
            retstr += " (%.2f @ %.0f)" % (rnge, bearing)

        elif bdsreg == 0x05:
          [altitude, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS05(msg.data, self._cpr)
          retstr += "Type 17 BDS0,5 (position report) from %x at (%.6f, %.6f)" % (icao24, decoded_lat, decoded_lon)
          if rnge is not None and bearing is not None:
            retstr += " (" + "%.2f" % rnge + " @ " + "%.0f" % bearing + ")"
          retstr += " at " + str(altitude) + "ft"

        elif bdsreg == 0x09:
          subtype = msg.data["bds09"].get_type()
          if subtype == 0:
            [velocity, heading, vert_spd, turnrate] = air_modes.parseBDS09_0(msg.data)
            retstr += "Type 17 BDS0,9-%i (track report) from %x with velocity %.0fkt heading %.0f VS %.0f turn rate %.0f" \
                     % (subtype, icao24, velocity, heading, vert_spd, turnrate)
          elif subtype == 1:
            [velocity, heading, vert_spd] = air_modes.parseBDS09_1(msg.data)
            retstr += "Type 17 BDS0,9-%i (track report) from %x with velocity %.0fkt heading %.0f VS %.0f" % (subtype, icao24, velocity, heading, vert_spd)
          elif subtype == 3:
            [mag_hdg, vel_src, vel, vert_spd, geo_diff] = air_modes.parseBDS09_3(msg.data)
            retstr += "Type 17 BDS0,9-%i (air course report) from %x with %s %.0fkt magnetic heading %.0f VS %.0f geo. diff. from baro. alt. %.0fft" \
                     % (subtype, icao24, vel_src, vel, mag_hdg, vert_spd, geo_diff)

          else:
            retstr += "Type 17 BDS0,9-%i from %x not implemented" % (subtype, icao24)

        elif bdsreg == 0x62:
          emerg_str = air_modes.parseBDS62(data)
          retstr += "Type 17 BDS6,2 (emergency) from %x type %s" % (icao24, emerg_str)

        else:
          retstr += "Type 17 with FTC=%i from %x not implemented" % (msg.data["ftc"], icao24)
    except ADSBError:
        return

    retstr += " with count= %i and hash= %x" %(msg.data["count"],msg.data["hash"])

    self._print(retstr)
Пример #8
0
 def receive(self, message, cpr_decoder):
     self.__last_heard_time = time.time(
     )  # TODO: arguably should be an argument
     # Unfortunately, gr-air-modes doesn't provide a function to implement this gunk -- imitating its output_flightgear code which
     data = message.data
     t = data.get_type()
     if t == 0:
         self.__altitude_feet = air_modes.decode_alt(data['ac'], True)
         # TODO more info available here
     elif t == 4:
         self.__altitude_feet = air_modes.decode_alt(data['ac'], True)
         # TODO more info available here
     elif t == 5:
         self.__ident = air_modes.decode_id(data['id'])
         # TODO more info available here
     elif t == 17:  # ADS-B
         bdsreg = data['me'].get_type()
         if bdsreg == 0x05:
             (self.__altitude_feet, self.__latitude, self.__longitude,
              _range, _bearing) = air_modes.parseBDS05(data, cpr_decoder)
         elif bdsreg == 0x06:
             (_ground_track, self.__latitude, self.__longitude, _range,
              _bearing) = air_modes.parseBDS06(data, cpr_decoder)
         elif bdsreg == 0x08:
             (self.__call,
              self.__aircraft_type) = air_modes.parseBDS08(data)
         elif bdsreg == 0x09:
             subtype = data['bds09'].get_type()
             if subtype == 0:
                 (self.__velocity, self.__heading, self.__vertical_speed,
                  self.__turn_rate) = air_modes.parseBDS09_0(data)
             elif subtype == 1:
                 (self.__velocity, self.__heading,
                  self.__vertical_speed) = air_modes.parseBDS09_1(data)
                 self.__turn_rate = 0  # TODO: or should we keep last?
             else:
                 # TODO report
                 pass
         else:
             # TODO report
             pass
     else:
         # TODO report
         pass
Пример #9
0
	def receive(self, message, cpr_decoder):
		self.__last_heard_time = time.time()  # TODO: arguably should be an argument
		# Unfortunately, gr-air-modes doesn't provide a function to implement this gunk -- imitating its output_flightgear code which
		data = message.data
		t = data.get_type()
		if t == 0:
			self.__altitude_feet = air_modes.decode_alt(data['ac'], True)
			# TODO more info available here
		elif t == 4:
			self.__altitude_feet = air_modes.decode_alt(data['ac'], True)
			# TODO more info available here
		elif t == 5:
			self.__ident = air_modes.decode_id(data['id'])
			# TODO more info available here
		elif t == 17:  # ADS-B
			bdsreg = data['me'].get_type()
			if bdsreg == 0x05:
				(self.__altitude_feet, self.__latitude, self.__longitude, _range, _bearing) = air_modes.parseBDS05(data, cpr_decoder)
			elif bdsreg == 0x06:
				(_ground_track, self.__latitude, self.__longitude, _range, _bearing) = air_modes.parseBDS06(data, cpr_decoder)
			elif bdsreg == 0x08:
				(self.__call, self.__aircraft_type) = air_modes.parseBDS08(data)
			elif bdsreg == 0x09:
				subtype = data['bds09'].get_type()
				if subtype == 0:
					(self.__velocity, self.__heading, self.__vertical_speed, self.__turn_rate) = air_modes.parseBDS09_0(data)
				elif subtype == 1:
					(self.__velocity, self.__heading, self.__vertical_speed) = air_modes.parseBDS09_1(data)
					self.__turn_rate = 0  # TODO: or should we keep last?
				else:
					# TODO report
					pass
			else:
				# TODO report
				pass
		else:
			# TODO report
			pass
Пример #10
0
    def sql17(self, data):
        icao24 = data["aa"]
        bdsreg = data["me"].get_type()
        #self["bds%.2i" % bdsreg] = icao24 #publish under "bds08", "bds06", etc.

        if bdsreg == 0x08:
            (msg, typename) = air_modes.parseBDS08(data)
            return "INSERT OR REPLACE INTO ident (icao, ident, type) VALUES (" + "%i" % icao24 + ", '" + msg + "', '" + typename + "')"
        elif bdsreg == 0x06:
            [ground_track, decoded_lat, decoded_lon, rnge,
             bearing] = air_modes.parseBDS06(data, self._cpr)
            altitude = 0
            if decoded_lat is None:  #no unambiguously valid position available
                raise CPRNoPositionError
            else:
                return "INSERT INTO positions (icao, seen, alt, lat, lon) VALUES (" + "%i" % icao24 + ", datetime('now'), " + str(
                    altitude
                ) + ", " + "%.6f" % decoded_lat + ", " + "%.6f" % decoded_lon + ")"
        elif bdsreg == 0x05:
            [altitude, decoded_lat, decoded_lon, rnge,
             bearing] = air_modes.parseBDS05(data, self._cpr)
            if decoded_lat is None:  #no unambiguously valid position available
                raise CPRNoPositionError
            else:
                return "INSERT INTO positions (icao, seen, alt, lat, lon) VALUES (" + "%i" % icao24 + ", datetime('now'), " + str(
                    altitude
                ) + ", " + "%.6f" % decoded_lat + ", " + "%.6f" % decoded_lon + ")"
        elif bdsreg == 0x09:
            subtype = data["bds09"].get_type()
            if subtype == 0:
                [velocity, heading, vert_spd,
                 turnrate] = air_modes.parseBDS09_0(data)
                return "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (" + "%i" % icao24 + ", datetime('now'), " + "%.0f" % velocity + ", " + "%.0f" % heading + ", " + "%.0f" % vert_spd + ")"
            elif subtype == 1:
                [velocity, heading, vert_spd] = air_modes.parseBDS09_1(data)
                return "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (" + "%i" % icao24 + ", datetime('now'), " + "%.0f" % velocity + ", " + "%.0f" % heading + ", " + "%.0f" % vert_spd + ")"
            else:
                raise NoHandlerError
Пример #11
0
 def receive(self, message_wrapper):
     message = message_wrapper.message
     cpr_decoder = message_wrapper.cpr_decoder
     receive_time = message_wrapper.receive_time
     self.__last_heard_time = receive_time
     # Unfortunately, gr-air-modes doesn't provide a function to implement this gunk -- imitating its output_flightgear code which
     data = message.data
     t = data.get_type()
     if t == 0:
         self.__track = self.__track._replace(
             altitude=TelemetryItem(air_modes.decode_alt(data['ac'], True) * _METERS_PER_FEET, receive_time))
         # TODO more info available here
     elif t == 4:
         self.__track = self.__track._replace(
             altitude=TelemetryItem(air_modes.decode_alt(data['ac'], True) * _METERS_PER_FEET, receive_time))
         # TODO more info available here
     elif t == 5:
         self.__ident = air_modes.decode_id(data['id'])
         # TODO more info available here
     elif t == 17:  # ADS-B
         bdsreg = data['me'].get_type()
         if bdsreg == 0x05:
             # TODO use unused info
             (altitude_feet, latitude, longitude, _range, _bearing) = air_modes.parseBDS05(data, cpr_decoder)
             self.__track = self.__track._replace(
                 altitude=TelemetryItem(altitude_feet * _METERS_PER_FEET, receive_time),
                 latitude=TelemetryItem(latitude, receive_time),
                 longitude=TelemetryItem(longitude, receive_time),
             )
         elif bdsreg == 0x06:
             # TODO use unused info
             (_ground_track, latitude, longitude, _range, _bearing) = air_modes.parseBDS06(data, cpr_decoder)
             self.__track = self.__track._replace(
                 latitude=TelemetryItem(latitude, receive_time),
                 longitude=TelemetryItem(longitude, receive_time),
             )
         elif bdsreg == 0x08:
             (self.__call, self.__aircraft_type) = air_modes.parseBDS08(data)
         elif bdsreg == 0x09:
             subtype = data['bds09'].get_type()
             if subtype == 0:
                 (velocity, heading, vertical_speed, _turn_rate) = air_modes.parseBDS09_0(data)
                 # TODO: note we're stuffing the heading in as track angle. Is there something better to do?
                 self.__track = self.__track._replace(
                     h_speed=TelemetryItem(velocity * _KNOTS_TO_METERS_PER_SECOND, receive_time),
                     heading=TelemetryItem(heading, receive_time),
                     track_angle=TelemetryItem(heading, receive_time),
                     v_speed=TelemetryItem(vertical_speed, receive_time),
                     # TODO add turn rate
                 )
             elif subtype == 1:
                 (velocity, heading, vertical_speed) = air_modes.parseBDS09_1(data)
                 self.__track = self.__track._replace(
                     h_speed=TelemetryItem(velocity * _KNOTS_TO_METERS_PER_SECOND, receive_time),
                     heading=TelemetryItem(heading, receive_time),
                     track_angle=TelemetryItem(heading, receive_time),
                     v_speed=TelemetryItem(vertical_speed, receive_time),
                     # TODO reset turn rate?
                 )
             else:
                 # TODO report
                 pass
         else:
             # TODO report
             pass
     else:
         # TODO report
         pass
Пример #12
0
 def receive(self, message_wrapper):
     message = message_wrapper.message
     cpr_decoder = message_wrapper.cpr_decoder
     receive_time = message_wrapper.receive_time
     self.__last_heard_time = receive_time
     # Unfortunately, gr-air-modes doesn't provide a function to implement this gunk -- imitating its output_flightgear code which
     data = message.data
     t = data.get_type()
     if t == 0:
         self.__track = self.__track._replace(altitude=TelemetryItem(
             air_modes.decode_alt(data['ac'], True) *
             _METERS_PER_FEET, receive_time))
         # TODO more info available here
     elif t == 4:
         self.__track = self.__track._replace(altitude=TelemetryItem(
             air_modes.decode_alt(data['ac'], True) *
             _METERS_PER_FEET, receive_time))
         # TODO more info available here
     elif t == 5:
         self.__ident = air_modes.decode_id(data['id'])
         # TODO more info available here
     elif t == 17:  # ADS-B
         bdsreg = data['me'].get_type()
         if bdsreg == 0x05:
             # TODO use unused info
             (altitude_feet, latitude, longitude, _range,
              _bearing) = air_modes.parseBDS05(data, cpr_decoder)
             self.__track = self.__track._replace(
                 altitude=TelemetryItem(altitude_feet * _METERS_PER_FEET,
                                        receive_time),
                 latitude=TelemetryItem(latitude, receive_time),
                 longitude=TelemetryItem(longitude, receive_time),
             )
         elif bdsreg == 0x06:
             # TODO use unused info
             (_ground_track, latitude, longitude, _range,
              _bearing) = air_modes.parseBDS06(data, cpr_decoder)
             self.__track = self.__track._replace(
                 latitude=TelemetryItem(latitude, receive_time),
                 longitude=TelemetryItem(longitude, receive_time),
             )
         elif bdsreg == 0x08:
             (self.__call,
              self.__aircraft_type) = air_modes.parseBDS08(data)
         elif bdsreg == 0x09:
             subtype = data['bds09'].get_type()
             if subtype == 0:
                 (velocity, heading, vertical_speed,
                  _turn_rate) = air_modes.parseBDS09_0(data)
                 # TODO: note we're stuffing the heading in as track angle. Is there something better to do?
                 self.__track = self.__track._replace(
                     h_speed=TelemetryItem(
                         velocity * _KNOTS_TO_METERS_PER_SECOND,
                         receive_time),
                     heading=TelemetryItem(heading, receive_time),
                     track_angle=TelemetryItem(heading, receive_time),
                     v_speed=TelemetryItem(vertical_speed, receive_time),
                     # TODO add turn rate
                 )
             elif subtype == 1:
                 (velocity, heading,
                  vertical_speed) = air_modes.parseBDS09_1(data)
                 self.__track = self.__track._replace(
                     h_speed=TelemetryItem(
                         velocity * _KNOTS_TO_METERS_PER_SECOND,
                         receive_time),
                     heading=TelemetryItem(heading, receive_time),
                     track_angle=TelemetryItem(heading, receive_time),
                     v_speed=TelemetryItem(vertical_speed, receive_time),
                     # TODO reset turn rate?
                 )
             else:
                 # TODO report
                 pass
         else:
             # TODO report
             pass
     else:
         # TODO report
         pass
     self.state_changed()