Welcome to ft8decoder’s documentation!

Core Classes

class ft8decoder.core.CQ(message: str, translated_message: str, caller: str, packet: Packet)[source]

Bases: object

Represents a CQ (calling any station) message in amateur radio.

CQ messages are general calls broadcast to invite any station to respond, typically used to initiate new contacts or conversations.

message

Original CQ message content

Type:

str

translated_message

Human-readable interpretation of the CQ

Type:

str

caller

Call sign of the station making the CQ call

Type:

str

packet

Packet object containing the raw signal data

Type:

ft8decoder.core.Packet

caller: str
message: str
packet: Packet
translated_message: str
class ft8decoder.core.MessageTurn(turn: int, message: str, translated_message: str, packet: Packet | str, type: str)[source]

Bases: object

Represents a single turn in a radio communication exchange.

turn

Sequential turn number in the conversation

Type:

int

message

Original raw message content

Type:

str

translated_message

Human-readable or decoded version of the message

Type:

str

packet

Associated Packet object or string identifier

Type:

ft8decoder.core.Packet | str

type

Type of message turn (e.g., “CQ”, “response”, “73”)

Type:

str

message: str
packet: Packet | str
translated_message: str
turn: int
type: str
class ft8decoder.core.Packet(snr: int, delta_time: float, frequency_offset: int, frequency: float, band: str, message: str, schema: int, program: str, time_captured: str, packet_type: int)[source]

Bases: object

Represents a WSJT-X UDP packet containing signal and metadata information for each captured FT8 message.

snr

Signal-to-noise ratio in decibels

Type:

int

delta_time

Time offset from expected timing in seconds

Type:

float

frequency_offset

Frequency offset from expected frequency in Hz

Type:

int

frequency

Actual received frequency in Hz or MHz

Type:

float

band

Radio frequency band (e.g., “20m”, “40m”, “2m”)

Type:

str

message

Raw message content from the packet

Type:

str

schema

Schema version or protocol identifier

Type:

int

program

Software/program that captured or processed the packet

Type:

str

time_captured

Timestamp when the packet was received (ISO format string)

Type:

str

packet_type

Numeric identifier for the type of packet

Type:

int

band: str
delta_time: float
frequency: float
frequency_offset: int
message: str
packet_type: int
program: str
schema: int
snr: int
time_captured: str

Parser Module

class ft8decoder.parser.WsjtxParser(dial_frequency: float, log_level=20)[source]

Bases: object

A UDP packet parser for WSJT-X FT8 messages.

This class listens for UDP packets from WSJT-X software, parses the binary packet data to extract FT8 message information, and queues the parsed packets for processing by a MessageProcessor.

The parser handles WSJT-X’s binary protocol format and converts frequency offsets to absolute frequencies while determining the amateur radio band based on the calculated frequency.

logger

Logger instance for this class

Type:

logging.Logger

packet_queue

Thread-safe queue for storing parsed packets

Type:

queue.Queue

dial_frequency

Base dial frequency in MHz from WSJT-X

Type:

float

Example

>>> parser = WsjtxParser(dial_frequency=14.074)
>>> processor = MessageProcessor()
>>> parser.start_listening('127.0.0.1', 2237, processor)
determine_band(frequency: float)[source]

Determine amateur radio band from frequency.

Maps the calculated frequency to the appropriate amateur radio band designation based on common FT8 frequencies. Uses a tolerance of ±15 kHz to account for frequency variations.

Parameters:

frequency (float) – Frequency in MHz to classify.

Returns:

Band designation (e.g., “20m”, “40m”, “80m”) or “Unknown”

if frequency doesn’t match any known FT8 band.

Return type:

str

Example

>>> parser = WsjtxParser(14.074)
>>> band = parser.determine_band(14.076)
>>> print(band)  # "20m"
frequency_handle(fq_offset: float)[source]

Convert WSJT-X frequency offset to absolute frequency.

WSJT-X sends frequency offsets in Hz relative to the dial frequency. This method converts the offset to MHz and adds it to the dial frequency to get the absolute transmission frequency.

Parameters:

fq_offset (float) – Frequency offset in Hz from WSJT-X packet data. Typically ranges from 0 to 3000 Hz for FT8.

Returns:

Absolute frequency in MHz. Returns dial_frequency if offset

is invalid.

Return type:

float

Example

>>> parser = WsjtxParser(14.074)
>>> freq = parser.frequency_handle(1500.0)  # 1500 Hz offset
>>> print(freq)  # 14.0755 MHz
listen(host, port, processor: MessageProcessor)[source]

Main UDP listening loop.

Creates a UDP socket, binds to the specified host/port, and continuously listens for WSJT-X packets. Packets are parsed and valid ones are added to the processing queue. Also starts a background thread to move packets from the queue to the processor.

Parameters:
  • host (str) – IP address to bind the UDP socket to.

  • port (int) – UDP port number to bind to.

  • processor (MessageProcessor) – Processor to handle parsed packets.

Note

This method runs in an infinite loop until a network error occurs. Uses a 1-second timeout on socket operations to prevent blocking.

parse_packets(data)[source]

Parse binary WSJT-X packet data into structured Packet objects.

Decodes the binary UDP packet format used by WSJT-X to extract message information including SNR, frequency offset, timestamp delta, and the decoded message text. Currently handles message packets (type 2) and ignores status packets (type 1).

Parameters:

data (bytes) – Raw UDP packet data from WSJT-X, minimum 12 bytes.

The WSJT-X packet format includes:
  • Header: Magic number, schema version, packet type

  • Message data: SNR, time delta, frequency offset, message text

Example packet structure for type 2 (message):

[0:4] Magic number [4:8] Schema version [8:12] Message type (2 for decoded messages) [27:31] SNR in dB [31:39] Time delta in seconds [39:43] Frequency offset in Hz [52:-2] UTF-8 encoded message text

start_grabbing(processor: MessageProcessor)[source]

Background thread to transfer packets from queue to processor.

Continuously monitors the packet queue and transfers parsed packets to the MessageProcessor’s data store. Runs in an infinite loop with a 1-second timeout to prevent blocking.

Parameters:

processor (MessageProcessor) – Processor instance to receive packets.

Note

This method runs in a separate thread and handles queue.Empty exceptions gracefully to avoid blocking when no packets are available.

start_listening(host, port, processor: MessageProcessor)[source]

Start the UDP listening process with user confirmation.

Prompts the user to confirm before starting packet capture, then launches the UDP listener in a separate thread. This is the main entry point for beginning FT8 packet capture.

Parameters:
  • host (str) – IP address to bind to, typically ‘127.0.0.1’ for localhost.

  • port (int) – UDP port number, typically 2237 for WSJT-X.

  • processor (MessageProcessor) – Processor instance to handle parsed packets.

Example

>>> parser = WsjtxParser(14.074)
>>> processor = MessageProcessor()
>>> parser.start_listening('127.0.0.1', 2237, processor)
Ready to listen on 127.0.0.1:2237...
Begin packet parsing? (Y/n)

Processor Module

class ft8decoder.processor.MessageProcessor(log_level=20)[source]

Bases: object

Processes and categorizes FT8 messages into QSOs, CQs, and miscellaneous communications.

This class takes parsed FT8 packets and intelligently categorizes them based on message content and structure. It tracks complete QSO (contact) sequences, identifies CQ calls, handles grid square exchanges, and provides data export and mapping functionality.

The processor understands FT8 protocol semantics including: - CQ calls (general and targeted) - Two-way QSO establishment and completion - Signal reports and grid square exchanges - Various acknowledgment and sign-off messages

logger

Logger for this class

Type:

logging.Logger

cqs

List of unmatched CQ calls

Type:

list

qso_coords

Coordinates for completed QSOs with grid squares

Type:

list

cq_coords

Coordinates for CQ calls with grid squares

Type:

list

grid_square_cache

Cache mapping callsigns to their grid squares

Type:

dict

data_motherload

Raw packet buffer from parser

Type:

list

misc_comms

Miscellaneous communications that don’t fit QSO pattern

Type:

dict

qso_dict

Complete QSO conversations indexed by sorted callsign pairs

Type:

dict

translation_templates

Templates for translating special CQ types

Type:

dict

master_data

Combined view of all processed data

Type:

list

Example

>>> processor = MessageProcessor()
>>> processor.start(seconds=5)  # Process packets every 5 seconds
>>> # After some time...
>>> processor.to_json("ft8_data")  # Export all data
>>> processor.to_map("ft8_map")   # Create world map
add_cq(callsigns: list)[source]

Link CQ calls to newly started QSOs.

When a new QSO begins, this method searches for any matching CQ call from one of the participants and incorporates it as the first turn of the conversation. This provides complete context for how the contact was initiated.

Parameters:

callsigns (list) – Sorted pair of callsigns starting a new QSO.

Process:
  1. Search through unmatched CQ calls

  2. Find CQ from either callsign in the new QSO

  3. Convert CQ to MessageTurn and insert as turn 1

  4. Remove CQ from unmatched list

Example

>>> # Previous CQ: "CQ W1ABC FN42"
>>> # New QSO starts: "W1ABC K2DEF"
>>> add_cq(["K2DEF", "W1ABC"])
>>> # CQ becomes turn 1 of the W1ABC/K2DEF conversation
comms_to_json(filename: str)[source]

Export QSO conversation data to JSON file.

Serializes all completed and in-progress QSO conversations to a JSON file for analysis, archival, or import into other applications. Each QSO is indexed by the sorted callsign pair and contains all message turns with metadata.

Parameters:

filename (str) – Output filename, .json extension added if missing.

Raises:
  • IOError – If file cannot be written due to permissions or disk space.

  • OSError – If filename/path is invalid.

JSON Structure:
{
“COMMS”: [{
“(‘CALL1’, ‘CALL2’)”: [

{“completed”: false}, {MessageTurn data…}, {MessageTurn data…}

]

}]

}

Example

>>> processor.comms_to_json("my_qsos")
>>> # Creates my_qsos.json with all QSO data
cqs_to_json(filename: str)[source]

Export unanswered CQ calls to JSON file.

Saves all CQ calls that have not yet been matched to QSO conversations. Useful for analyzing calling patterns, popular frequencies, and propagation conditions.

Parameters:

filename (str) – Output filename, .json extension added if missing.

Raises:
  • IOError – If file cannot be written.

  • OSError – If filename/path is invalid.

JSON Structure:
{
“CQS”: [

{CQ object data…}, {CQ object data…}

]

}

Example

>>> processor.cqs_to_json("unanswered_cqs")
>>> # Creates unanswered_cqs.json with CQ data
gather_coords()[source]

Collect and resolve geographic coordinates for QSOs and CQ calls.

Processes the grid square cache to convert Maidenhead locators into latitude/longitude coordinates for mapping purposes. Creates coordinate tuples for both QSOs (with connection lines, as long as both participants have sent their grid squares) and CQ calls (as individual points).

Coordinate Resolution Process:
  1. Check QSO participants for cached grid squares

  2. Resolve grid squares to lat/lon coordinates

  3. Create QSO coordinate tuples with both endpoints

  4. Process CQ calls similarly for standalone points

Populates:

self.qso_coords: List of QSO coordinate tuples self.cq_coords: List of CQ coordinate tuples

QSO Coordinate Format:

((callsign1, lat1, lon1), (callsign2, lat2, lon2), (timestamp,))

CQ Coordinate Format:

(message, timestamp, latitude, longitude)

Example

>>> processor.gather_coords()
>>> print(f"Found {len(processor.qso_coords)} QSOs with coordinates")
>>> print(f"Found {len(processor.cq_coords)} CQs with coordinates")
handle_ack_reply(callsigns: list, packet: Packet, message: list)[source]

Process acknowledgment and sign-off messages in QSOs.

Handles the final stages of FT8 QSOs where stations confirm receipt of information and formally conclude the contact. Different acknowledgment types have specific meanings and some mark the QSO as completed.

Parameters:
  • callsigns (list) – Sorted pair of callsigns involved in the QSO.

  • packet (Packet) – The packet containing the acknowledgment.

  • message (list) – Message words, with acknowledgment code as last element.

Acknowledgment Processing:
  • “RRR”: Simple confirmation, QSO implied complete

  • “RR73”: Confirmation + goodbye, marks QSO as completed

  • “73”: Goodbye message, marks QSO as completed

Example

>>> # Message: ["W1ABC", "K2DEF", "RR73"]
>>> handle_ack_reply(["K2DEF", "W1ABC"], packet, message)
>>> # Marks QSO as completed and adds final turn
handle_cq(packet: Packet)[source]

Process CQ (calling any station) messages.

CQ calls are the foundation of amateur radio contacts, indicating that a station is available for communication. This method handles various CQ formats from simple general calls to complex targeted calls with event indicators.

Parameters:

packet (Packet) – The packet containing the CQ message.

CQ Message Formats:
  • 2 words: “CQ CALLSIGN” (general call)

  • 3 words: “CQ CALLSIGN GRID” (call with location)

  • 4 words: “CQ EVENT CALLSIGN GRID” (targeted/special event call)

Example

>>> handle_cq(packet)  # packet.message = "CQ W1ABC FN42"
>>> # Creates: "Station W1ABC is calling for any response from grid FN42."
handle_grid_square(callsigns: list, packet: Packet, message: list)[source]

Process grid square location exchanges in QSOs.

Grid square exchanges are a standard part of FT8 QSOs, allowing operators to share their geographic locations. The grid square is cached for later use in mapping and coordinate resolution.

Parameters:
  • callsigns (list) – Sorted pair of callsigns involved in the QSO.

  • packet (Packet) – The packet containing the grid square.

  • message (list) – Message words, with grid square as the last element.

Example

>>> # Message: ["W1ABC", "K2DEF", "FN42"]
>>> handle_grid_square(["K2DEF", "W1ABC"], packet, message)
>>> # Creates: "K2DEF sends a grid square location of FN42 to W1ABC."
handle_longer_msg(packet: Packet, message: list)[source]

Process messages with more than three words.

Handles specialized CQ calls that include specific targets or event indicators. These four-word messages typically follow the format: “CQ EVENT CALLSIGN GRID” where EVENT specifies the type of activity or geographic target.

Parameters:
  • packet (Packet) – The packet containing the multi-word message.

  • message (list) – List of words from the message (4+ words expected).

Expected Format:

message[0]: “CQ” (already verified by caller) message[1]: Event/target code (e.g., “DX”, “POTA”, “TEST”, “NA”) message[2]: Calling station’s callsign message[3]: Calling station’s grid square

Example

>>> handle_longer_msg(packet, ["CQ", "POTA", "W1ABC", "FN42"])
>>> # Creates: "Parks on the Air participant W1ABC is calling from grid FN42."
handle_short_msg(packet: Packet, message: list)[source]

Process two-word FT8 messages.

Handles various two-word message types including grid square announcements, sign-offs, acknowledgments, and QRP (low power) indicators. These messages are typically not part of structured QSOs but provide important information or conclude conversations.

Parameters:
  • packet (Packet) – The packet containing the two-word message.

  • message (list) – List of two words from the message.

Message Types:
  • Grid announcements: “CALLSIGN GRID” (e.g., “W1ABC FN42”)

  • Sign-offs: “CALLSIGN 73” (goodbye message)

  • Roger + sign-off: “CALLSIGN RR73” (acknowledgment + goodbye)

  • QRP indicators: “CALLSIGN/QRP CALLSIGN” (low power operations)

  • Simple pings: “CALLSIGN1 CALLSIGN2” (basic contact attempt)

Example

>>> handle_short_msg(packet, ["W1ABC", "FN42"])  # Grid announcement
>>> handle_short_msg(packet, ["W1ABC", "73"])    # Sign-off
>>> handle_short_msg(packet, ["W1ABC/QRP", "K2DEF"])  # QRP ping
handle_signal_report(callsigns: list, packet: Packet, message: list)[source]

Process FT8 signal report exchanges.

Signal reports are a critical part of FT8 QSOs, indicating how well each station is receiving the other. This method creates a MessageTurn object with appropriate human-readable translation and adds it to the ongoing QSO conversation.

Parameters:
  • callsigns (list) – Sorted pair of callsigns involved in the QSO.

  • packet (Packet) – The packet containing the signal report.

  • message (list) – Message words, with signal report as the last element.

Signal Report Translation:
  • Reports with ‘R’ prefix indicate acknowledgment of previous report

  • Numeric value represents signal-to-noise ratio in dB

  • Positive values indicate strong signals, negative indicate weak

Example

>>> # Message: ["W1ABC", "K2DEF", "R-08"]
>>> handle_signal_report(["K2DEF", "W1ABC"], packet, message)
>>> # Creates: "K2DEF says Roger and reports a signal report of -08 to W1ABC."
is_ack_reply(message)[source]

Determine if a message is an acknowledgment or sign-off.

FT8 conversations typically end with acknowledgment codes that confirm receipt of information and/or indicate the QSO is complete.

Parameters:

message (list) – List of words from the FT8 message.

Returns:

True if the message ends with a recognized acknowledgment code.

Return type:

bool

Acknowledgment Types:
  • “RRR”: Roger Roger Roger (confirmation received)

  • “RR73”: Roger Roger + 73 (confirmation + goodbye)

  • “73”: Best wishes/goodbye (QSO completion)

Example

>>> is_ack_reply(["W1ABC", "K2DEF", "RRR"])   # True
>>> is_ack_reply(["W1ABC", "K2DEF", "RR73"])  # True
>>> is_ack_reply(["W1ABC", "K2DEF", "FN42"])  # False
is_grid_square(message)[source]

Determine if a message contains a Maidenhead grid square locator.

Maidenhead grid squares are a coordinate system used by amateur radio operators to specify geographic location. They follow the format of two uppercase letters followed by two digits (e.g., FN42, IO91).

Parameters:

message (list) – List of words from the FT8 message.

Returns:

True if the last word is a valid 4-character grid square.

Return type:

bool

Grid Square Format:
  • Character 1: Uppercase letter (A-R, longitude field)

  • Character 2: Uppercase letter (A-R, latitude field)

  • Character 3: Digit (0-9, longitude square)

  • Character 4: Digit (0-9, latitude square)

Example

>>> is_grid_square(["W1ABC", "K2DEF", "FN42"])  # True (valid grid)
>>> is_grid_square(["W1ABC", "K2DEF", "fn42"])  # False (lowercase)
>>> is_grid_square(["W1ABC", "K2DEF", "FN4"])   # False (too short)
is_signal_report(message: list)[source]

Determine if a message contains an FT8 signal report.

FT8 signal reports are numeric values (typically -24 to +50 dB) that indicate signal strength and decoding quality. They may be prefixed with ‘R’ (received/roger) or ‘RR’ (roger roger) to indicate acknowledgment.

Parameters:

message (list) – List of words from the FT8 message.

Returns:

True if the last word appears to be a signal report.

Return type:

bool

Signal Report Formats:
  • Simple: “+05”, “-15”, “00” (raw SNR values)

  • Roger: “R+05”, “R-15” (acknowledging receipt)

  • Roger Roger: “RR+05”, “RR-15” (confirming exchange)

Example

>>> is_signal_report(["W1ABC", "K2DEF", "-15"])  # True
>>> is_signal_report(["W1ABC", "K2DEF", "R+05"])  # True
>>> is_signal_report(["W1ABC", "K2DEF", "73"])    # False
misc_to_json(filename: str)[source]

Export miscellaneous communications to JSON file.

Saves communications that don’t fit the standard QSO pattern, including grid announcements, standalone sign-offs, and unrecognized message formats. Useful for debugging message parsing and analyzing non-standard activity.

Parameters:

filename (str) – Output filename, .json extension added if missing.

Raises:
  • IOError – If file cannot be written.

  • OSError – If filename/path is invalid.

Example

>>> processor.misc_to_json("misc_messages")
>>> # Creates misc_messages.json
organize_messages(seconds: int)[source]

Main message processing loop that categorizes FT8 messages.

This method runs continuously in a background thread, processing accumulated packets at regular intervals. It handles the complete FT8 message classification workflow:

  1. Copies and clears the packet buffer

  2. Parses each message to identify type (CQ, QSO, misc)

  3. Routes messages to appropriate handlers

  4. Tracks QSO progression and completion

Parameters:

seconds (int) – Sleep interval between processing cycles.

Message Classification Logic:
  • CQ messages: Start with “CQ” keyword

  • Two-word messages: Grid squares, sign-offs, acknowledgments

  • Three-word messages: Standard QSO exchanges (callsign pairs + data)

  • Four+ word messages: Special CQs with targets/events

Example message flows:
>>> # CQ sequence
>>> "CQ W1ABC FN42" -> handle_cq()
>>> "W1ABC K2DEF" -> new QSO started
>>> "K2DEF W1ABC -15" -> signal report
>>> "W1ABC K2DEF FN42" -> grid square
>>> "K2DEF W1ABC RRR" -> acknowledgment
>>> "W1ABC K2DEF 73" -> QSO completed
resolve_grid_square(grid_square)[source]

Convert Maidenhead grid square to latitude/longitude coordinates.

Uses the maidenhead library to convert 4-character grid squares into decimal degree coordinates for mapping and distance calculations. Returns a dictionary with coordinate information and a Google Maps link.

Parameters:

grid_square (str) – 4-character Maidenhead grid square (e.g., “FN42”).

Returns:

Dictionary containing grid square, coordinates, and map URL.

Returns None if conversion fails.

Return type:

dict or None

Return Format:
{

“Grid Square”: “FN42”, “Latitude”: “42.5”, “Longitude”: “-71.5”, “Map URL”: “https://www.google.com/maps?q=42.5,-71.5

}

Example

>>> coords = resolve_grid_square("FN42")
>>> print(f"Location: {coords['Latitude']}, {coords['Longitude']}")
>>> # Location: 42.5, -71.5
sort_message(packet: Packet, callsigns: list, new_convo: bool)[source]

Route QSO messages to appropriate handlers based on content.

This method analyzes three-word FT8 messages (typically callsign pairs plus additional data) and routes them to specialized handlers based on the message type. For new conversations, it also searches for and incorporates any matching CQ call.

Parameters:
  • packet (Packet) – The packet containing the message to process.

  • callsigns (list) – Sorted list of two callsigns from the message.

  • new_convo (bool) – True if this is the first message in a QSO.

Message Types Handled:
  • Acknowledgments: RRR, RR73, 73 (conversation enders)

  • Grid squares: 4-character locator codes (e.g., FN42, IO91)

  • Signal reports: Numeric SNR values with optional R/RR prefix

  • Unknown: Added to misc_comms for manual review

Example

>>> # New QSO starting
>>> sort_message(packet, ['K2DEF', 'W1ABC'], new_convo=True)
>>> # Continues existing QSO
>>> sort_message(packet, ['K2DEF', 'W1ABC'], new_convo=False)
start(seconds=5)[source]

Start the message processing thread.

Launches a background thread that periodically processes accumulated packets from the data buffer. The thread runs continuously, processing packets at the specified interval.

Parameters:

seconds (int, optional) – Interval between processing cycles in seconds. Defaults to 5. Shorter intervals provide more real-time processing but use more CPU.

Example

>>> processor = MessageProcessor()
>>> processor.start(seconds=3)  # Process every 3 seconds
to_json(filename: str)[source]

Export all captured FT8 data to a comprehensive JSON file.

Creates a complete export containing QSO conversations, unanswered CQ calls, and miscellaneous communications in a single file. This is the most comprehensive export option for complete session analysis.

Parameters:

filename (str) – Output filename, .json extension added if missing.

Raises:
  • IOError – If file cannot be written due to permissions or disk space.

  • OSError – If filename/path is invalid.

JSON Structure:
{

“COMMS”: [{QSO conversations…}], “CQS”: [{CQ calls…}], “MISC. COMMS”: [{miscellaneous messages…}]

}

Example

>>> processor.to_json("complete_session")
>>> # Creates complete_session.json with all data types
to_map(filename: str, all_cqs: bool = True)[source]

Generate an interactive world map of FT8 activity.

Creates a Folium-based HTML map showing QSO connections as lines between stations and CQ calls as individual markers. The map is automatically centered based on QSO activity and includes interactive layers for different data types.

Parameters:
  • filename (str) – Output filename for the HTML map (without .html extension).

  • all_cqs (bool, optional) – If True, show all CQ calls. If False, only show CQs from stations that have not participated in a QSO. Defaults to True.

Raises:

Exception – If map generation fails due to coordinate resolution errors or file writing issues.

Map Features:
  • QSO participants: Green radio icons with callsign popups

  • QSO connections: Blue lines connecting stations with QSO details

  • CQ calls: Red radio icons for unanswered calls

  • Layer control: Toggle between QSOs and CQs

  • Auto-centering: Map centers on mean QSO coordinates

Map Centering Logic:
  • If 3+ QSOs with coordinates: Centers on mean lat/lon of all participants

  • If <3 QSOs: Uses default world view (0,0) coordinates

Example

>>> processor.to_map("activity_map")
>>> # Creates activity_map.html with all QSOs and CQs
>>> processor.to_map("qso_only", all_cqs=False)
>>> # Creates qso_only.html showing only successful contacts

CLI Module

ft8decoder.cli.main()[source]

Main entry point for the FT8 Decoder command-line interface.

Provides a comprehensive CLI for capturing, processing, and exporting FT8 messages from WSJT-X. Supports real-time packet capture with configurable processing intervals and multiple export formats including JSON data files and interactive world maps.

Command Structure:

ft8decoder listen [options]

Key Features:
  • Real-time FT8 packet capture from WSJT-X UDP stream

  • Intelligent message classification (QSOs, CQs, misc communications)

  • Multiple export formats (JSON, interactive maps)

  • Configurable processing intervals and capture duration

  • Automatic band detection and frequency calculation

Example Usage:

$ python main.py listen –dial 14.074 –duration 300 –export-all session1 $ python main.py listen –port 2237 –interval 10 –to-map activity_map $ python main.py listen –host 192.168.1.100 –export-comms qsos_only

Indices and tables