### Track Aircraft with Tracker Class Source: https://github.com/enok71/adsb/blob/main/README.md Instantiate the `Tracker` class and process incoming ADSB messages to track aircraft. This example assumes messages are read line by line, stripped, encoded to bytes, and then parsed. ```python from adsb import Tracker tracker = Tracker() for msg in readline(): m = Adsb.parse(msg.strip().encode()) tracker.process(m) ``` -------------------------------- ### Decode Vertical Rate with AirborneVelocities.altitude_rate() Source: https://context7.com/enok71/adsb/llms.txt Retrieves the vertical rate in ft/min from the 9-bit vertical rate field. The source can be Barometric or GNSS, indicated by `.vrsrc`. Returns None when the field is zero, signifying no information. ```python from adsb import Adsb frame = Adsb.parse(0x8DA05F219B06B6AF189400CBC33F) vel = frame.data vr = vel.altitude_rate() src = "GNSS" if vel.vrsrc else "Baro" print(f"Vertical rate ({src}): {vr} ft/min" if vr is not None else "No vertical rate info") ``` -------------------------------- ### Decode Aircraft Heading with AirborneVelocities.heading() Source: https://context7.com/enok71/adsb/llms.txt Returns the true track angle or magnetic heading in degrees. Sub-types 1/2 derive from velocity components, while 3/4 use the heading field. Returns None if the relevant fields lack information. ```python from adsb import Adsb frame = Adsb.parse(0x8DA05F219B06B6AF189400CBC33F) vel = frame.data hdg = vel.heading() print(f"Track/Heading: {hdg:.2f}°" if hdg is not None else "Not available") ``` -------------------------------- ### Decode Aircraft Speed with AirborneVelocities.speed() Source: https://context7.com/enok71/adsb/llms.txt Retrieves ground or airspeed in knots. Sub-types 2 and 4 indicate supersonic speeds (values multiplied by 4). Returns None if velocity information is unavailable. ```python from adsb import Adsb frame = Adsb.parse(0x8DA05F219B06B6AF189400CBC33F) vel = frame.data # AirborneVelocities spd = vel.speed() hdg = vel.heading() vr = vel.altitude_rate() print(f"Speed : {spd:.1f} kn" if spd else "Speed : N/A") print(f"Heading : {hdg:.1f}°" if hdg else "Heading : N/A") print(f"Vert. rate: {vr} ft/min" if vr else "Vert. rate: N/A") # Example output: # Speed : 425.3 kn # Heading : 182.5° # Vert. rate: -64 ft/min ``` -------------------------------- ### AirborneVelocities.altitude_rate() Source: https://context7.com/enok71/adsb/llms.txt Decodes and returns the aircraft's vertical rate in feet per minute. It indicates whether the source is barometric or GNSS. Returns None if the vertical rate field is zero. ```APIDOC ## AirborneVelocities.altitude_rate() ### Description Returns the vertical rate in ft/min (positive = climbing, negative = descending) from the 9-bit vertical rate field. The source may be barometric or GNSS as indicated by `.vrsrc`. Returns `None` when the field is zero (no information). ### Method `altitude_rate()` ### Parameters None ### Response - **altitude_rate** (int or None): The vertical rate in ft/min, or None if unavailable. - **vrsrc** (bool): True if the vertical rate source is GNSS, False if Barometric. ### Request Example ```python from adsb import Adsb frame = Adsb.parse(0x8DA05F219B06B6AF189400CBC33F) vel = frame.data vr = vel.altitude_rate() src = "GNSS" if vel.vrsrc else "Baro" print(f"Vertical rate ({src}): {vr} ft/min" if vr is not None else "No vertical rate info") ``` ### Response Example ``` Vertical rate (Baro): -64 ft/min ``` ``` -------------------------------- ### Manage Per-Aircraft State with Vehicle Class Source: https://context7.com/enok71/adsb/llms.txt The `Vehicle` class stores the latest decoded state for an individual aircraft, including ICAO address, timestamps, position history, speed, and heading. It is typically managed by `Tracker` but can be instantiated and updated manually. ```python from adsb.tracker import Vehicle from adsb import Adsb v = Vehicle(icao=0x4840D6) msgs = [ 0x8D40621D58C382D690C8AC2863A7, 0x8D40621D58C386435CC412692AD6, ] for raw in msgs: frame = Adsb.parse(raw.to_bytes(14, 'big')) if frame: # Manually route to a specific vehicle frame.icao = v.icao # align ICAO for demo v.process(frame) print(v) # icao=4840d6: lat=52.257202 lon=3.919373 speed=None heading=None print(f"Last seen: {v.last_seen}") ``` -------------------------------- ### Track Aircraft with Tracker Class Source: https://context7.com/enok71/adsb/llms.txt The `Tracker` class maintains state for multiple aircraft, keyed by ICAO address. It processes incoming `Adsb` frames, updating each `Vehicle` object with the latest information. New aircraft are automatically registered upon first contact. ```python from adsb import Adsb, Tracker tracker = Tracker() raw_messages = [ b'\x8D\x48\x40\xD6\x20\x2C\xC3\x71\xC3\x2C\xE0\x57\x60\x98', 0x8D40621D58C382D690C8AC2863A7, 0x8D40621D58C386435CC412692AD6, # odd-frame pair → CPR position resolved 0x8D485020994409940838175B284F, 0x8DA05F219B06B6AF189400CBC33F, ] for raw in raw_messages: if isinstance(raw, int): raw = raw.to_bytes(14, 'big') frame = Adsb.parse(raw) if frame is not None: tracker.process(frame) # Inspect all tracked aircraft for icao, vehicle in tracker.vehicles.items(): print(vehicle) # icao=4840d6: lat=None lon=None speed=None heading=None # icao=40621d: lat=52.257202 lon=3.919373 speed=None heading=None # icao=485020: lat=None lon=None speed=None heading=None # icao=a05f21: lat=None lon=None speed=425.30 heading=182.50 ``` -------------------------------- ### AirborneVelocities.speed() Source: https://context7.com/enok71/adsb/llms.txt Decodes and returns the aircraft's ground speed or airspeed in knots. It handles different sub-types for raw data and supersonic variants. Returns None if speed information is unavailable. ```APIDOC ## AirborneVelocities.speed() ### Description Returns ground speed (sub-types 1/2) or airspeed (sub-types 3/4) in knots computed from the east/west and north/south velocity components or the raw airspeed field. Sub-type 2 and 4 are supersonic variants (values multiplied by 4). Returns `None` if velocity information is unavailable. ### Method `speed()` ### Parameters None ### Response - **speed** (float or None): The aircraft's speed in knots, or None if unavailable. ### Request Example ```python from adsb import Adsb frame = Adsb.parse(0x8DA05F219B06B6AF189400CBC33F) vel = frame.data # AirborneVelocities spd = vel.speed() print(f"Speed : {spd:.1f} kn" if spd else "Speed : N/A") ``` ### Response Example ``` Speed : 425.3 kn ``` ``` -------------------------------- ### AirborneVelocities.heading() Source: https://context7.com/enok71/adsb/llms.txt Decodes and returns the aircraft's true track angle or magnetic heading in degrees. It distinguishes between track derived from velocity components and heading from a dedicated field. Returns None if heading information is unavailable. ```APIDOC ## AirborneVelocities.heading() ### Description Returns the true track angle (sub-types 1/2, derived from velocity components) or the magnetic heading (sub-types 3/4, from the heading field) in degrees [0–360). Returns `None` if the relevant fields carry no information. ### Method `heading()` ### Parameters None ### Response - **heading** (float or None): The aircraft's heading in degrees, or None if unavailable. ### Request Example ```python from adsb import Adsb frame = Adsb.parse(0x8DA05F219B06B6AF189400CBC33F) vel = frame.data hdg = vel.heading() print(f"Track/Heading: {hdg:.2f}°" if hdg is not None else "Not available") ``` ### Response Example ``` Track/Heading: 182.50° ``` ``` -------------------------------- ### Compute ADS-B 24-bit CRC with crc(m) Source: https://context7.com/enok71/adsb/llms.txt Calculates the 24-bit CRC-24 checksum for ADS-B messages using the standard polynomial 0x1FFF409. Accepts input as bytes or an integer. A valid, uncorrupted 112-bit message will result in a checksum of 0. Useful for verifying message integrity or constructing new frames. ```python from adsb.crc import crc # Verify a known-good message msg = b'\x8D\x48\x40\xD6\x20\x2C\xC3\x71\xC3\x2C\xE0\x57\x60\x98' result = crc(msg) print(result) # 0 → message is valid # Compute checksum of a message without the last 3 bytes (for building new frames) msg_no_crc = msg[:11] checksum = crc(msg_no_crc + b'\x00\x00\x00') print(hex(checksum)) # 24-bit value to append # Works with int too result_int = crc(0x8D4840D6202CC371C32CE0576098) print(result_int) # 0 ``` -------------------------------- ### Tracker Source: https://context7.com/enok71/adsb/llms.txt A stateful tracker that maintains a collection of `Vehicle` objects, keyed by ICAO address. It processes incoming `Adsb` frames, routing them to the appropriate `Vehicle` to update its state. ```APIDOC ## Tracker ### Description `Tracker` maintains a dictionary of `Vehicle` objects keyed by ICAO address. Each call to `Tracker.process(adsb)` routes the decoded `Adsb` frame to the matching `Vehicle`, which accumulates position history (for CPR decoding), speed, heading, and ADS-B version. New aircraft are registered automatically on first contact. ### Methods - **process(frame: Adsb)**: Processes a decoded `Adsb` frame, updating the state of the corresponding `Vehicle`. ### Properties - **vehicles** (dict): A dictionary mapping ICAO addresses to `Vehicle` objects. ### Request Example ```python from adsb import Adsb, Tracker tracker = Tracker() raw_messages = [ b'\x8D\x48\x40\xD6\x20\x2C\xC3\x71\xC3\x2C\xE0\x57\x60\x98', 0x8D40621D58C382D690C8AC2863A7, 0x8D40621D58C386435CC412692AD6, # odd-frame pair → CPR position resolved 0x8D485020994409940838175B284F, 0x8DA05F219B06B6AF189400CBC33F, ] for raw in raw_messages: if isinstance(raw, int): raw = raw.to_bytes(14, 'big') frame = Adsb.parse(raw) if frame is not None: tracker.process(frame) # Inspect all tracked aircraft for icao, vehicle in tracker.vehicles.items(): print(vehicle) ``` ### Response Example ``` icao=4840d6: lat=None lon=None speed=None heading=None icao=40621d: lat=52.257202 lon=3.919373 speed=None heading=None icao=485020: lat=None lon=None speed=None heading=None icao=a05f21: lat=None lon=None speed=425.30 heading=182.50 ``` ``` -------------------------------- ### Vehicle Source: https://context7.com/enok71/adsb/llms.txt A container for the state of a single aircraft, including its ICAO address, last seen timestamp, position history, decoded coordinates, speed, and heading. It is typically managed by the `Tracker` but can be used independently. ```APIDOC ## Vehicle ### Description `Vehicle` holds the latest decoded state for a single aircraft: ICAO address, last-seen timestamp, CPR position history, decoded lat/lon, speed, heading, and ADS-B version. It is created and updated automatically by `Tracker` but can also be instantiated directly. ### Methods - **process(frame: Adsb)**: Processes a decoded `Adsb` frame, updating the vehicle's state. ### Properties - **icao** (int): The ICAO address of the aircraft. - **last_seen** (datetime): The timestamp when the aircraft was last seen. - **lat** (float or None): The decoded latitude, or None if unavailable. - **lon** (float or None): The decoded longitude, or None if unavailable. - **speed** (float or None): The decoded speed in knots, or None if unavailable. - **heading** (float or None): The decoded heading in degrees, or None if unavailable. ### Request Example ```python from adsb.tracker import Vehicle from adsb import Adsb v = Vehicle(icao=0x4840D6) msgs = [ 0x8D40621D58C382D690C8AC2863A7, 0x8D40621D58C386435CC412692AD6, ] for raw in msgs: frame = Adsb.parse(raw.to_bytes(14, 'big')) if frame: # Manually route to a specific vehicle frame.icao = v.icao # align ICAO for demo v.process(frame) print(v) print(f"Last seen: {v.last_seen}") ``` ### Response Example ``` icao=4840d6: lat=52.257202 lon=3.919373 speed=None heading=None Last seen: 2023-10-27 10:00:00.123456 ``` ``` -------------------------------- ### AirbornePosition.altitude() Source: https://context7.com/enok71/adsb/llms.txt Decodes the barometric or GNSS altitude from the 12-bit encoded altitude field in an AirbornePosition message. ```APIDOC ## AirbornePosition.altitude() — Decode barometric or GNSS altitude ### Description Returns the altitude in feet decoded from the 12-bit encoded altitude field. Supports both Gillham (25 ft resolution) and standard (100 ft resolution) encodings. Returns `None` when no altitude information is available (encoded value is 0). ### Method `AirbornePosition.altitude() -> Optional[int]` ### Parameters None ### Request Example ```python from adsb import Adsb frame = Adsb.parse(0x8D40621D58C382D690C8AC2863A7) pos = frame.data # AirbornePosition alt_ft = pos.altitude() if alt_ft is not None: print(f"Altitude: {alt_ft} ft ({alt_ft * 0.3048:.1f} m)") else: print("Altitude not available") ``` ### Response #### Success Response (Optional[int]) - Returns the altitude in feet as an integer, or `None` if altitude is not available. #### Response Example ``` 38000 ``` ``` -------------------------------- ### Decode Altitude from AirbornePosition Source: https://context7.com/enok71/adsb/llms.txt The `AirbornePosition.altitude()` method decodes the 12-bit encoded altitude field into feet. It supports both Gillham (25 ft resolution) and standard (100 ft resolution) encodings. Returns `None` if the encoded value is 0. ```python from adsb import Adsb frame = Adsb.parse(0x8D40621D58C382D690C8AC2863A7) pos = frame.data # AirbornePosition alt_ft = pos.altitude() if alt_ft is not None: print(f"Altitude: {alt_ft} ft ({alt_ft * 0.3048:.1f} m)") else: print("Altitude not available") # Example output: Altitude: 38000 ft (11582.4 m) ``` -------------------------------- ### AirbornePosition.position(last_position=None) Source: https://context7.com/enok71/adsb/llms.txt Decodes Compact Position Reporting (CPR) encoded latitude and longitude from a pair of ADS-B position messages (even and odd parity). ```APIDOC ## AirbornePosition.position(last_position=None) — Decode CPR latitude/longitude ### Description Decodes the Compact Position Reporting (CPR) encoded lat/lon from a pair of ADS-B position messages (one even, one odd). Returns `(lat, lon)` in decimal degrees, or `(None, None)` if both frames are not yet available or both have the same parity flag. ### Method `AirbornePosition.position(last_position: Optional[AirbornePosition] = None) -> Tuple[Optional[float], Optional[float]]` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from adsb import Adsb from adsb.adsb import AirbornePosition # Two successive position messages for the same aircraft msg_even = Adsb.parse(0x8D40621D58C382D690C8AC2863A7) msg_odd = Adsb.parse(0x8D40621D58C386435CC412692AD6) pos_even = msg_even.data # AirbornePosition, f=0 (even) pos_odd = msg_odd.data # AirbornePosition, f=1 (odd) lat, lon = pos_odd.position(last_position=pos_even) if lat is not None: print(f"Aircraft at {lat:.6f}°, {lon:.6f}°") else: print("Need both an even and an odd frame to decode position") ``` ### Response #### Success Response (Tuple[Optional[float], Optional[float]]) - Returns a tuple containing latitude and longitude in decimal degrees. If decoding is not possible, returns `(None, None)`. #### Response Example ``` (40.712778, -74.005973) ``` ``` -------------------------------- ### Parse ADSB Messages from Bytes or Integer Source: https://github.com/enok71/adsb/blob/main/README.md Use the `Adsb.parse` method to decode ADSB messages. It accepts messages as either an integer or a bytes object. Ensure the input is correctly formatted. ```python from adsb import Adsb print(Adsb.parse(0x8D40621D58C382D690C8AC2863A7)) ``` ```python print(Adsb.parse(b'\x8D\x48\x40\xD6\x20\x2C\xC3\x71\xC3\x2C\xE0\x57\x60\x98')) ``` -------------------------------- ### crc(m) Source: https://context7.com/enok71/adsb/llms.txt Computes the 24-bit CRC-24 checksum for ADS-B messages. It accepts messages as bytes or integers and returns 0 for valid, uncorrupted messages. ```APIDOC ## crc(m) ### Description Computes the 24-bit CRC-24 checksum over the 112-bit message using the standard ADS-B generator polynomial `0x1FFF409`. Accepts either `bytes` or `int`. For a valid, uncorrupted 112-bit message (data + appended checksum), the result is `0`. ### Method `crc(m)` ### Parameters - **m** (bytes or int): The ADS-B message data, with or without the CRC checksum. ### Response - **crc** (int): The computed 24-bit CRC checksum. ### Request Example ```python from adsb.crc import crc # Verify a known-good message msg = b'\x8D\x48\x40\xD6\x20\x2C\xC3\x71\xC3\x2C\xE0\x57\x60\x98' result = crc(msg) print(result) # 0 → message is valid # Compute checksum of a message without the last 3 bytes (for building new frames) msg_no_crc = msg[:11] checksum = crc(msg_no_crc + b'\x00\x00\x00') print(hex(checksum)) # 24-bit value to append # Works with int too result_int = crc(0x8D4840D6202CC371C32CE0576098) print(result_int) # 0 ``` ### Response Example ``` 0 0x1c32e0 0 ``` ``` -------------------------------- ### Encode ADS-B Message to Bytes Source: https://context7.com/enok71/adsb/llms.txt Use the `encode()` method on an `Adsb` object to serialize it back into a 112-bit `bytes` representation. This includes the DF/CA byte, ICAO address, and a computed CRC. ```python from adsb import Adsb from adsb.adsb import AircraftId # Reconstruct an Adsb object manually and encode it payload = AircraftId(tc=1, ec=0, callsign="BAW123 ") frame = Adsb(ca=5, icao=0x4840D6, data=payload) raw = frame.encode() print(raw.hex()) # 112-bit message with valid CRC appended # Round-trip: parse → encode → re-parse original = Adsb.parse(b'\x8D\x48\x40\xD6\x20\x2C\xC3\x71\xC3\x2C\xE0\x57\x60\x98') # Note: encode() is fully implemented only for message types whose # AdsbData subclass has encode() defined (currently AircraftId & Unknown). ``` -------------------------------- ### Decode CPR Position from Two Messages Source: https://context7.com/enok71/adsb/llms.txt The `AirbornePosition.position()` method decodes Compact Position Reporting (CPR) encoded latitude and longitude from a pair of ADS-B position messages (one even, one odd). It returns `(lat, lon)` or `(None, None)` if frames are missing or have the same parity. ```python from adsb import Adsb from adsb.adsb import AirbornePosition # Two successive position messages for the same aircraft msg_even = Adsb.parse(0x8D40621D58C382D690C8AC2863A7) msg_odd = Adsb.parse(0x8D40621D58C386435CC412692AD6) pos_even = msg_even.data # AirbornePosition, f=0 (even) pos_odd = msg_odd.data # AirbornePosition, f=1 (odd) lat, lon = pos_odd.position(last_position=pos_even) if lat is not None: print(f"Aircraft at {lat:.6f}°, {lon:.6f}°") else: print("Need both an even and an odd frame to decode position") ``` -------------------------------- ### Adsb.encode() Source: https://context7.com/enok71/adsb/llms.txt Encodes an Adsb object back into a 112-bit bytes representation, including the DF/CA byte, ICAO address, and a computed CRC. ```APIDOC ## Adsb.encode() — Encode an ADS-B message to bytes ### Description Assembles an `Adsb` object back into a 112-bit `bytes` representation by serialising the inner `AdsbData` payload, prepending the DF/CA byte and 24-bit ICAO address, and appending a computed 24-bit CRC. ### Method `Adsb.encode() -> bytes` ### Parameters None ### Request Example ```python from adsb import Adsb from adsb.adsb import AircraftId # Reconstruct an Adsb object manually and encode it payload = AircraftId(tc=1, ec=0, callsign="BAW123 ") frame = Adsb(ca=5, icao=0x4840D6, data=payload) raw = frame.encode() print(raw.hex()) # 112-bit message with valid CRC appended # Round-trip: parse → encode → re-parse original = Adsb.parse(b'\x8D\x48\x40\xD6\x20\x2C\xC3\x71\xC3\x2C\xE0\x57\x60\x98') # Note: encode() is fully implemented only for message types whose # AdsbData subclass has encode() defined (currently AircraftId & Unknown). ``` ### Response #### Success Response (bytes) - Returns the 112-bit raw ADS-B message as a `bytes` object. #### Response Example ``` '8d4840d6202cc371c32ce0576098' ``` ``` -------------------------------- ### Handle Invalid ADS-B Messages Source: https://context7.com/enok71/adsb/llms.txt When `Adsb.parse()` receives a message with a bad CRC or a non-ADS-B Downlink Format, it returns `None`. ```python from adsb import Adsb # Bad CRC / non-ADS-B message returns None bad = Adsb.parse(b'\x00' * 14) assert bad is None ``` -------------------------------- ### Parse ADS-B Message from Integer Source: https://context7.com/enok71/adsb/llms.txt Use `Adsb.parse()` to decode a raw 112-bit ADS-B message provided as an integer. The function validates the CRC and returns an `Adsb` object or `None` for invalid messages. ```python from adsb import Adsb # Parse from int (hex literal) frame2 = Adsb.parse(0x8D40621D58C382D690C8AC2863A7) print(frame2) # ads-b(ca="...", icao=40621d, data=AirbornePosition(...)) ``` -------------------------------- ### Parse ADS-B Message from Bytes Source: https://context7.com/enok71/adsb/llms.txt Use `Adsb.parse()` to decode a raw 112-bit ADS-B message provided as bytes. The function validates the CRC and returns an `Adsb` object or `None` for invalid messages. ```python from adsb import Adsb # Parse from bytes msg_bytes = b'\x8D\x48\x40\xD6\x20\x2C\xC3\x71\xC3\x2C\xE0\x57\x60\x98' frame = Adsb.parse(msg_bytes) print(frame) # ads-b(ca="Level 2+ transponder with ability to set CA to 7, airborne", # icao=4840d6, data=AirbornePosition(...)) ``` -------------------------------- ### Adsb.parse(msg) Source: https://context7.com/enok71/adsb/llms.txt Parses a raw 112-bit ADS-B message provided as bytes or an integer. It validates the CRC and returns an Adsb object with the decoded payload or None if the message is invalid. ```APIDOC ## Adsb.parse(msg) — Parse a raw ADS-B message ### Description Parses a 112-bit ADS-B message supplied as `bytes` or `int`. Verifies the 24-bit CRC first; returns `None` on a bad checksum or non-ADS-B Downlink Format. On success, returns an `Adsb` object whose `.data` attribute holds the decoded payload as the appropriate `AdsbData` subclass. ### Method `Adsb.parse(msg: Union[bytes, int]) -> Optional[Adsb]` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from adsb import Adsb # Parse from bytes msg_bytes = b'\x8D\x40\x40\xD6\x20\x2C\xC3\x71\xC3\x2C\xE0\x57\x60\x98' frame = Adsb.parse(msg_bytes) print(frame) # Parse from int (hex literal) frame2 = Adsb.parse(0x8D40621D58C382D690C8AC2863A7) print(frame2) # Bad CRC / non-ADS-B message returns None bad = Adsb.parse(b'\x00' * 14) assert bad is None ``` ### Response #### Success Response (Adsb Object) - **data** (AdsbData subclass): The decoded payload of the ADS-B message. #### Response Example ``` adsb(ca="Level 2+ transponder with ability to set CA to 7, airborne", icao=4840d6, data=AirbornePosition(...)) ``` #### Error Response (None) - Returns `None` if the message has a bad CRC or is not an ADS-B Downlink Format. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.