New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

ka9q-python

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ka9q-python

Python interface for ka9q-radio control and monitoring

pipPyPI
Version
3.4.2
Maintainers
1

ka9q-python

PyPI version License: MIT

General-purpose Python library for controlling ka9q-radio

Control radiod channels for any application: AM/FM/SSB radio, WSPR monitoring, SuperDARN radar, CODAR oceanography, HF fax, satellite downlinks, and more.

Note: Package name is ka9q-python out of respect for KA9Q (Phil Karn's callsign). Import as import ka9q.

Table of Contents

Features

Zero assumptions - Works for any SDR application
Complete API - All 85+ radiod parameters exposed
Channel control - Create, configure, discover channels
RTP recording - Generic recorder with timing support and state machine
Precise timing - GPS_TIME/RTP_TIMESNAP for accurate timestamps
Multi-homed support - Works on systems with multiple network interfaces
Pure Python - No compiled dependencies
Well tested - Comprehensive test coverage
Documented - Comprehensive examples and API reference included

Installation

pip install ka9q-python

Or install from source:

git clone https://github.com/mijahauan/ka9q-python.git
cd ka9q-python
pip install -e .

Quick Start

Host selection: All examples reference bee1-hf-status.local, which is the default integration test radiod in this repo. Replace it with your own radiod host or set RADIOD_HOST, RADIOD_ADDRESS, or the --radiod-host pytest option when running in other environments.

Listen to AM Broadcast

from ka9q import RadiodControl

# Connect to radiod (default test host: bee1-hf-status.local)
control = RadiodControl("bee1-hf-status.local")

# Create AM channel on 10 MHz WWV
control.create_channel(
    ssrc=10000000,
    frequency_hz=10.0e6,
    preset="am",
    sample_rate=12000
)

# RTP stream now available with SSRC 10000000

### Request Specific Output Encoding

```python
from ka9q import RadiodControl, Encoding

control = RadiodControl("bee1-hf-status.local")

# Create a channel with 32-bit float output (highest quality)
control.ensure_channel(
    frequency_hz=14.074e6,
    preset="usb",
    sample_rate=12000,
    encoding=Encoding.F32
)

### Monitor WSPR Bands

```python
from ka9q import RadiodControl

control = RadiodControl("bee1-hf-status.local")

wspr_bands = [
    (1.8366e6, "160m"),
    (3.5686e6, "80m"),
    (7.0386e6, "40m"),
    (10.1387e6, "30m"),
    (14.0956e6, "20m"),
]

for freq, band in wspr_bands:
    control.create_channel(
        ssrc=int(freq),
        frequency_hz=freq,
        preset="usb",
        sample_rate=12000
    )
    print(f"{band} WSPR channel created")

Discover Existing Channels

from ka9q import discover_channels

channels = discover_channels("bee1-hf-status.local")
for ssrc, info in channels.items():
    print(f"{ssrc}: {info.frequency/1e6:.3f} MHz, {info.preset}, {info.sample_rate} Hz")

Record RTP Stream with Precise Timing

from ka9q import discover_channels, RTPRecorder
import time

# Get channel with timing info
channels = discover_channels("bee1-hf-status.local")
channel = channels[14074000]

# Define packet handler
def handle_packet(header, payload, wallclock):
    print(f"Packet at {wallclock}: {len(payload)} bytes")

# Create and start recorder
recorder = RTPRecorder(channel=channel, on_packet=handle_packet)
recorder.start()
recorder.start_recording()
time.sleep(60)  # Record for 60 seconds
recorder.stop_recording()
recorder.stop()

Multi-Homed Systems

For systems with multiple network interfaces, specify which interface to use:

from ka9q import RadiodControl, discover_channels

# Specify your interface IP address
my_interface = "192.168.1.100"

# Create control with specific interface
control = RadiodControl("bee1-hf-status.local", interface=my_interface)

# Discovery on specific interface
channels = discover_channels("bee1-hf-status.local", interface=my_interface)

Automatic Channel Recovery

ensure your channels survive radiod restarts:

from ka9q import RadiodControl, ChannelMonitor

control = RadiodControl("bee1-hf-status.local")
monitor = ChannelMonitor(control)
monitor.start()

# This channel will be automatically re-created if it disappears
monitor.monitor_channel(
    frequency_hz=14.074e6,
    preset="usb",
    sample_rate=12000
)

### Channel Cleanup (frequency = 0)

`radiod` removes channels by polling for streams whose frequency is set to `0 Hz`. Always call `remove_channel(ssrc)` (or explicitly set `set_frequency(ssrc, 0.0)` if you build TLVs yourself) when tearing down a stream so the background poller can reclaim it:

```python
with RadiodControl("bee1-hf-status.local") as control:
    info = control.ensure_channel(
        frequency_hz=10e6,
        preset="iq",
        sample_rate=16000
    )

    # ... use channel ...

    control.remove_channel(info.ssrc)  # marks frequency=0

Note: remove_channel() finishes instantly on the client; radiod’s poller typically purges the channel within the next second.

Documentation

For detailed information, please refer to the documentation in the docs/ directory:

Examples

See the examples/ directory for complete applications:

  • High-Level API: ensure_channel() handles the complexity of checking existing channels, creating new ones only when necessary, and verifying configurations.
  • Destination-Aware Channels: Support for unique per-application multicast destinations and deterministic IP generation.
  • Stream Sharing: Deterministic SSRC allocation allows multiple independent applications to share radiod streams efficiently.
  • discover_example.py - Channel discovery methods (native Python and control utility)
  • tune.py - Interactive channel tuning utility (Python implementation of ka9q-radio's tune)
  • tune_example.py - Programmatic examples of using the tune() method
  • rtp_recorder_example.py - Complete RTP recorder with timing and state machine
  • test_timing_fields.py - Verify GPS_TIME/RTP_TIMESNAP timing fields
  • simple_am_radio.py - Minimal AM broadcast listener
  • superdarn_recorder.py - Ionospheric radar monitoring
  • codar_oceanography.py - Ocean current radar
  • hf_band_scanner.py - Dynamic frequency scanner
  • wspr_monitor.py - Weak signal propagation reporter

Use Cases

AM/FM/SSB Radio

  • Broadcast monitoring
  • Ham radio operation
  • Shortwave listening

Scientific Research

  • WSPR propagation studies
  • SuperDARN ionospheric radar
  • CODAR ocean current mapping
  • Meteor scatter
  • EME (moonbounce)

Digital Modes

  • FT8/FT4 monitoring
  • RTTY/PSK decoding
  • DRM digital radio
  • HF fax reception

Satellite Operations

  • Downlink reception
  • Doppler tracking
  • Multi-frequency monitoring

Custom Applications

No assumptions! Use for anything SDR-related.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Keywords

ka9q-radio

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts