Releases: mijahauan/ka9q-python
v3.4.2: Bug Fixes and Enhanced Documentation
Release v3.4.2: Bug Fixes and Enhanced Documentation
This release focuses on improving the user experience through bug fixes, comprehensive documentation, and better organization of examples.
π Bug Fixes
Fixed stream_example.py Bug
Fixed a critical bug in examples/stream_example.py where the code incorrectly iterated over the dictionary returned by discover_channels(). The example now correctly accesses ChannelInfo objects, preventing an AttributeError and allowing the example to run as intended.
This was a high-impact bug that would have prevented new users from successfully running one of the key examples.
π Documentation Enhancements
New Getting Started Guide
Added a comprehensive docs/GETTING_STARTED.md file that serves as the primary entry point for new users. This guide includes:
- Step-by-step installation instructions
- A simple, annotated first program (creating an AM radio channel)
- Detailed explanations of core concepts (
RadiodControl,ChannelInfo, stream abstraction layers) - A comparison table of the three stream APIs (
RTPRecorder,RadiodStream,ManagedStream) - Complete working examples with
ManagedStream - Common troubleshooting tips
Examples Organization
Added a new examples/README.md that transforms the examples directory into a structured learning resource:
- Categorizes examples by complexity (basic, intermediate, advanced)
- Provides detailed descriptions for each example (what it does, concepts demonstrated, how to run it)
- Recommends a learning path for new users
- Includes usage instructions and expected output for each example
Updated API Documentation
The documentation for create_channel() in docs/API_REFERENCE.md has been updated to match the actual implementation:
- Added missing
destinationparameter (for RTP destination multicast address) - Added missing
encodingparameter (for output encoding like F32, S16LE, OPUS) - Corrected parameter order to match the actual function signature
- Added return type documentation (returns
intSSRC) - Enhanced examples with both basic and advanced usage patterns
Updated Main README
The main README.md now links prominently to the new Getting Started guide, making it easier for new users to find the beginner-friendly tutorial.
π Impact
These changes significantly improve the user onboarding experience:
- For new users: Clear, guided path from installation to first working application
- For existing users: No breaking changes, just better documentation and a bug fix
- For contributors: Better structure makes it easier to understand and contribute
π¦ Installation
pip install ka9q-python==3.4.2Or upgrade from a previous version:
pip install --upgrade ka9q-pythonπ Links
- Getting Started Guide: docs/GETTING_STARTED.md
- Examples Guide: examples/README.md
- API Reference: docs/API_REFERENCE.md
- Full Changelog: CHANGELOG.md
π Full Changelog
Added
- Comprehensive Getting Started Guide: Added
docs/GETTING_STARTED.mdwith step-by-step tutorial for new users - Examples README: Added
examples/README.mdto organize examples by complexity and provide learning path
Fixed
stream_example.pyBug: Fixed incorrect dictionary iteration that causedAttributeError
Changed
- Updated API Documentation: Complete documentation for
create_channel()including all parameters - Updated README: Added link to Getting Started guide
Full Changelog: v3.4.1...v3.4.2
v3.3.0: ManagedStream for self-healing RTP streams
New Features
- ManagedStream class: Wraps RadiodStream with automatic drop detection and channel restoration when radiod restarts
- StreamState enum: Track stream health (STOPPED, STARTING, HEALTHY, DROPPED, RESTORING)
- ManagedStreamStats: Monitor drops, restorations, and healthy/dropped durations
- Callbacks: Get notified on stream drop and restoration events
Usage
from ka9q import RadiodControl, ManagedStream
stream = ManagedStream(
control=control,
frequency_hz=14.074e6,
preset='usb',
sample_rate=12000,
on_samples=callback,
on_stream_dropped=on_drop,
on_stream_restored=on_restore,
drop_timeout_sec=3.0,
restore_interval_sec=1.0,
)
channel = stream.start()This enables robust streaming applications that automatically recover from radiod restarts without manual intervention.
Installation
pip install ka9q-python==3.3.0v3.2.7
Added
- ChannelMonitor: New service that provides automatic recovery from
radiodrestarts. It monitors registered channels and automatically invokesensure_channelto restore them if they disappear.- Usage:
monitor = ChannelMonitor(control); monitor.start(); monitor.monitor_channel(...)
- Usage:
v3.2.6
Added
- Output Encoding Support: Added complete support for specifying output encoding (e.g., F32, S16LE, OPUS) in
ensure_channelandcreate_channel.create_channelnow automatically sends the required follow-upOUTPUT_ENCODINGcommand toradiod.ensure_channelverifies the encoding of existing channels and reconfigures them if different from the requested encoding.ChannelInfonow includes theencodingfield for discovered channels.
Release v3.2.5
Added
- Destination-Aware Channels:
ka9q-pythonnow supports unique destination IP addresses per client application. Theensure_channelandcreate_channelmethods now accept adestinationparameter. - Unique IP Generation: Added
generate_multicast_ip(unique_id)helper function to deterministically map application IDs to the239.0.0.0/8multicast range. - Improved SSRC Allocation:
allocate_ssrcnow includes the destination address in its hash calculation, ensuring that streams with different destinations get unique SSRCs.
v3.2.4 - Fix resequencer for fragmented IQ packets
Fixed
- Resequencer Fragmented IQ Support - Fixed resequencer to correctly handle fragmented IQ packets from radiod. The resequencer now uses actual packet sample count for timestamp tracking instead of the fixed
samples_per_packetvalue. This prevents false gap detection when radiod fragments large IQ payloads (e.g., IQ 20kHz F32 fragments into 1440+1440+320 byte packets).
Added
- Channel Verification Test Suite - Comprehensive test suite (
tests/test_channel_verification.py) that verifies radiod channel creation, encoding, sample rate, and destination configuration.
Install
pip install ka9q-python==3.2.4v3.2.3: Fix socket reconnection vulnerability
Fixed
- Socket Reconnection Vulnerability - Fixed vulnerability where socket errors would terminate the receive loop permanently. Both
RadiodStreamandRTPRecordernow implement automatic reconnection with exponential backoff (1s to 60s max). This provides robustness against:- Network interface restarts
- Multicast group membership drops
- Transient network errors
ka9q-python v3.2.0 - RadiodStream API
ka9q-python v3.2.0 Release Notes
π RadiodStream API - Continuous Sample Delivery with Quality Tracking
This release adds a high-level streaming API that delivers continuous sample streams with comprehensive quality metadata. Designed for applications like GRAPE, WSPR, CODAR, and SuperDARN that need reliable data capture with gap detection and quality metrics.
Installation
pip install ka9q-python
# or
pip install git+https://github.com/mijahauan/ka9q-python.gitWhat's New
RadiodStream - High-Level Streaming
from ka9q import RadiodStream, StreamQuality, discover_channels
def on_samples(samples, quality: StreamQuality):
print(f"Got {len(samples)} samples, {quality.completeness_pct:.1f}% complete")
channels = discover_channels('radiod.local')
stream = RadiodStream(channel=channels[10000000], on_samples=on_samples)
stream.start()
# ... your application runs ...
final_quality = stream.stop()StreamQuality - Comprehensive Metrics
Every callback receives quality metadata:
| Metric | Description |
|---|---|
completeness_pct |
Percentage of expected samples received |
total_gap_events |
Number of distinct gaps detected |
total_gaps_filled |
Total zero-fill samples inserted |
rtp_packets_received |
Packets received from multicast |
rtp_packets_lost |
Packets never received (sequence gaps) |
rtp_packets_resequenced |
Out-of-order packets that were resequenced |
first_rtp_timestamp |
RTP timestamp of first packet (for precise timing) |
GapEvent - Gap Classification
for gap in quality.batch_gaps:
print(f"Gap at sample {gap.position_samples}")
print(f" Type: {gap.source.value}") # network_loss, resequence_timeout, etc.
print(f" Duration: {gap.duration_samples} samples")PacketResequencer - Reliable Delivery
- Circular buffer handles network jitter (configurable, default 64 packets)
- KA9Q-style signed 32-bit timestamp arithmetic for wrap handling
- Zero-fills gaps to maintain sample count integrity
- Detects and logs out-of-order and lost packets
Architecture
radiod β Multicast β RadiodStream β PacketResequencer β App Callback
β
StreamQuality (per batch + cumulative)
Core (ka9q-python) delivers:
- Continuous sample stream (gaps zero-filled)
- Quality metadata with every callback
- RTP timestamps for precise timing
Applications handle:
- Segmentation (1-minute NPZ, 2-minute WAV, etc.)
- Format conversion
- App-specific gap classification
Examples
Two new examples demonstrate the API:
examples/stream_example.py- Basic streaming with quality reportingexamples/grape_integration_example.py- Two-phase recording (startup buffer β recording)
New Exports
from ka9q import (
# Stream API (NEW)
RadiodStream,
StreamQuality,
GapSource,
GapEvent,
PacketResequencer,
RTPPacket,
ResequencerStats,
# Existing
RadiodControl,
discover_channels,
ChannelInfo,
# ...
)Compatibility
- Python 3.8+
- Linux, macOS, Windows (multicast support)
- Works with ka9q-radio (radiod)
Full Changelog
See CHANGELOG.md for complete release history.
ka9q-python v3.1.0
ka9q-python v3.1.0 π―
SSRC Abstraction - Simplified Channel Creation
This release removes SSRC from application concerns. Applications now specify what they want (frequency, mode, sample rate) and the system handles SSRC allocation internally.
π What's New
SSRC-Free API
No more manual SSRC management! The create_channel() method now automatically allocates SSRCs when not specified:
from ka9q import RadiodControl
# New simplified API (recommended)
with RadiodControl("radiod.local") as control:
ssrc = control.create_channel(
frequency_hz=14.074e6,
preset="usb",
sample_rate=12000
)
print(f"Created channel with SSRC: {ssrc}")Key Features:
- π― Optional SSRC - Method returns the SSRC (useful when auto-allocated)
- π Deterministic allocation - Same parameters always produce the same SSRC
- π€ Cross-library compatibility - Matches signal-recorder's allocation algorithm
- π‘ Stream sharing - Multiple apps can share the same stream automatically
New allocate_ssrc() Function
For advanced use cases requiring coordination:
from ka9q import allocate_ssrc
# Pre-allocate SSRC for coordination
ssrc = allocate_ssrc(
frequency_hz=10.0e6,
preset="iq",
sample_rate=16000
)
# Use with create_channel() or share with other appsπ API Changes
create_channel() signature updated:
frequency_hzis now the first required parameterssrcmoved to the end and made optional- Method now returns the SSRC (int) instead of None
Before (v3.0.0):
control.create_channel(ssrc=12345, frequency_hz=14.074e6, preset="usb")After (v3.1.0):
# Auto-allocate (recommended)
ssrc = control.create_channel(frequency_hz=14.074e6, preset="usb")
# Or specify manually (still supported)
ssrc = control.create_channel(frequency_hz=14.074e6, preset="usb", ssrc=12345)π€ Cross-Library Compatibility
The SSRC allocation algorithm matches signal-recorder's StreamSpec.ssrc_hash():
key = (round(frequency_hz), preset.lower(), sample_rate, agc, round(gain, 1))
return hash(key) & 0x7FFFFFFFBenefits:
- Same parameters β same SSRC in both libraries
- Automatic stream sharing across applications
- No coordination overhead needed
π‘ Use Cases
Simple Channel Creation:
# Just specify what you want - SSRC handled automatically
ssrc = control.create_channel(14.074e6, "usb", 12000)Stream Sharing Between Apps:
# App 1: Creates channel
ssrc1 = control.create_channel(7.074e6, "usb", 12000)
# App 2: Same parameters β same SSRC β shared stream
ssrc2 = control.create_channel(7.074e6, "usb", 12000)
# ssrc1 == ssrc2 (stream is shared!)Coordinated Recording:
# Both ka9q-python and signal-recorder use the same SSRC
ssrc = allocate_ssrc(14.074e6, "usb", 12000)
# Now both apps receive the same RTP streamβ Backward Compatibility
100% backward compatible - Existing code with explicit SSRCs continues to work without modification. The SSRC parameter is still supported, just optional.
π¦ Installation
pip install ka9q==3.1.0Or upgrade:
pip install --upgrade ka9qπ Documentation
- CHANGELOG.md - Complete version history
- README.md - Updated with new API examples
π Credits
SSRC allocation algorithm inspired by Phil Karn's ka9q-radio project.
π Issues & Feedback
Found a bug or have a feature request? Please open an issue on GitHub:
https://github.com/mijahauan/ka9q-python/issues
Full Changelog: https://github.com/mijahauan/ka9q-python/blob/main/CHANGELOG.md
ka9q-python v3.0.0
ka9q-python v3.0.0 π
Complete RadioD Feature Exposure
This major release provides comprehensive control over all ka9q-radio features through the Python interface. We've exposed 20 new control methods, covering everything from satellite tracking to spectrum analysis.
π What's New
20 New Control Methods
Satellite & Advanced Tuning
- π°οΈ
set_doppler()- Real-time Doppler tracking for satellites - π‘
set_first_lo()- Direct hardware tuner control
Signal Processing
- π
set_pll()- Phase-locked loop for carrier tracking - π
set_squelch()- SNR-based squelch with hysteresis - π»
set_envelope_detection()- AM envelope vs synchronous detection - ποΈ
set_independent_sideband()- ISB mode (USB/LSB to L/R) - πΆ
set_fm_threshold_extension()- Weak FM signal improvement
Audio & Output
- π
set_output_channels()- Mono/stereo control - π΅
set_output_encoding()- Format selection (PCM, Opus) - πΏ
set_opus_bitrate()- Opus quality control - π¦
set_packet_buffering()- Latency vs packet rate trade-off - π
set_destination()- Dynamic output routing
Filtering & Analysis
- ποΈ
set_filter2()- Secondary filter for selectivity - π
set_spectrum()- Spectrum analyzer configuration - π―
set_agc_threshold()- AGC activation tuning
System Control
- βοΈ
set_status_interval()- Status reporting rate - π
set_demod_type()- Dynamic mode switching - π»
set_rf_gain()/set_rf_attenuation()- RF hardware control - π¬
set_options()- Experimental features
π Documentation
New Guides:
- NEW_FEATURES.md - Detailed documentation with examples
- QUICK_REFERENCE.md - Quick lookup guide
- examples/advanced_features_demo.py - Working demo script
π‘ Example Use Cases
Satellite Tracking:
from ka9q import RadiodControl
control = RadiodControl("radiod.local")
control.set_doppler(
ssrc=12345,
doppler_hz=-5000,
doppler_rate_hz_per_sec=100
)Coherent AM Reception:
# Enable PLL for carrier tracking
control.set_pll(ssrc=12345, enable=True, bandwidth_hz=50)
control.set_envelope_detection(ssrc=12345, enable=False)ISB Mode (USB & LSB simultaneously):
control.set_independent_sideband(ssrc=12345, enable=True)
control.set_output_channels(ssrc=12345, channels=2)High-Quality Opus Streaming:
from ka9q.types import Encoding
control.set_output_encoding(ssrc=12345, encoding=Encoding.OPUS)
control.set_opus_bitrate(ssrc=12345, bitrate=128000)Spectrum Analysis:
control.set_spectrum(
ssrc=12345,
bin_bw_hz=100,
bin_count=512,
kaiser_beta=6.0
)β Complete Feature Coverage
This release provides comprehensive coverage of radiod's TLV command set:
β
All 35+ radiod commands now supported
β
Doppler tracking for satellite reception
β
PLL carrier tracking
β
SNR squelch with hysteresis
β
Independent sideband mode
β
FM threshold extension
β
Secondary filtering
β
Spectrum analyzer
β
Output encoding control
β
RF hardware controls
β
Experimental options
π Backward Compatibility
100% backward compatible - All existing code continues to work without modification. All changes are additive.
π¦ Installation
pip install ka9q==3.0.0Or upgrade:
pip install --upgrade ka9qπ§ͺ Testing
Run the demo script to see all new features:
python3 examples/advanced_features_demo.pyπ Full Documentation
- NEW_FEATURES.md - Complete feature documentation
- QUICK_REFERENCE.md - Quick reference with examples
- CHANGELOG.md - Detailed changelog
- RADIOD_FEATURES_SUMMARY.md - Implementation details
π Credits
Thanks to Phil Karn (KA9Q) for creating ka9q-radio and making its source code available for analysis.
π Issues & Feedback
Found a bug or have a feature request? Please open an issue on GitHub:
https://github.com/mijahauan/ka9q-python/issues
Full Changelog: https://github.com/mijahauan/ka9q-python/blob/main/CHANGELOG.md