ka9q-python 3.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ka9q_python-3.2.0/LICENSE +21 -0
- ka9q_python-3.2.0/MANIFEST.in +21 -0
- ka9q_python-3.2.0/PKG-INFO +237 -0
- ka9q_python-3.2.0/README.md +202 -0
- ka9q_python-3.2.0/examples/advanced_features_demo.py +116 -0
- ka9q_python-3.2.0/examples/channel_cleanup_example.py +249 -0
- ka9q_python-3.2.0/examples/codar_oceanography.py +88 -0
- ka9q_python-3.2.0/examples/discover_example.py +106 -0
- ka9q_python-3.2.0/examples/grape_integration_example.py +255 -0
- ka9q_python-3.2.0/examples/hf_band_scanner.py +121 -0
- ka9q_python-3.2.0/examples/rtp_recorder_example.py +196 -0
- ka9q_python-3.2.0/examples/simple_am_radio.py +36 -0
- ka9q_python-3.2.0/examples/stream_example.py +195 -0
- ka9q_python-3.2.0/examples/superdarn_recorder.py +71 -0
- ka9q_python-3.2.0/examples/test_channel_operations.py +346 -0
- ka9q_python-3.2.0/examples/test_improvements.py +226 -0
- ka9q_python-3.2.0/examples/test_timing_fields.py +80 -0
- ka9q_python-3.2.0/examples/tune.py +284 -0
- ka9q_python-3.2.0/examples/tune_example.py +124 -0
- ka9q_python-3.2.0/ka9q/__init__.py +98 -0
- ka9q_python-3.2.0/ka9q/control.py +2295 -0
- ka9q_python-3.2.0/ka9q/discovery.py +485 -0
- ka9q_python-3.2.0/ka9q/exceptions.py +23 -0
- ka9q_python-3.2.0/ka9q/resequencer.py +389 -0
- ka9q_python-3.2.0/ka9q/rtp_recorder.py +457 -0
- ka9q_python-3.2.0/ka9q/stream.py +393 -0
- ka9q_python-3.2.0/ka9q/stream_quality.py +215 -0
- ka9q_python-3.2.0/ka9q/types.py +161 -0
- ka9q_python-3.2.0/ka9q/utils.py +202 -0
- ka9q_python-3.2.0/ka9q_python.egg-info/PKG-INFO +237 -0
- ka9q_python-3.2.0/ka9q_python.egg-info/SOURCES.txt +52 -0
- ka9q_python-3.2.0/ka9q_python.egg-info/dependency_links.txt +1 -0
- ka9q_python-3.2.0/ka9q_python.egg-info/requires.txt +5 -0
- ka9q_python-3.2.0/ka9q_python.egg-info/top_level.txt +1 -0
- ka9q_python-3.2.0/pyproject.toml +52 -0
- ka9q_python-3.2.0/setup.cfg +4 -0
- ka9q_python-3.2.0/setup.py +47 -0
- ka9q_python-3.2.0/tests/__init__.py +0 -0
- ka9q_python-3.2.0/tests/conftest.py +14 -0
- ka9q_python-3.2.0/tests/test_decode_functions.py +253 -0
- ka9q_python-3.2.0/tests/test_encode_functions.py +329 -0
- ka9q_python-3.2.0/tests/test_encode_socket.py +122 -0
- ka9q_python-3.2.0/tests/test_integration.py +442 -0
- ka9q_python-3.2.0/tests/test_listen_multicast.py +78 -0
- ka9q_python-3.2.0/tests/test_multihomed.py +192 -0
- ka9q_python-3.2.0/tests/test_native_discovery.py +345 -0
- ka9q_python-3.2.0/tests/test_performance_fixes.py +223 -0
- ka9q_python-3.2.0/tests/test_remove_channel.py +161 -0
- ka9q_python-3.2.0/tests/test_security_features.py +319 -0
- ka9q_python-3.2.0/tests/test_tune.py +231 -0
- ka9q_python-3.2.0/tests/test_tune_cli.py +312 -0
- ka9q_python-3.2.0/tests/test_tune_debug.py +212 -0
- ka9q_python-3.2.0/tests/test_tune_live.py +173 -0
- ka9q_python-3.2.0/tests/test_tune_method.py +381 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Michael James Hauan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION OF THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Include documentation
|
|
2
|
+
include README.md
|
|
3
|
+
include LICENSE
|
|
4
|
+
include SUMMARY.md
|
|
5
|
+
include TUNE_IMPLEMENTATION.md
|
|
6
|
+
include NATIVE_DISCOVERY.md
|
|
7
|
+
include CROSS_PLATFORM_SUPPORT.md
|
|
8
|
+
include TEST_RESULTS.md
|
|
9
|
+
include TESTING_SUMMARY.md
|
|
10
|
+
|
|
11
|
+
# Include examples
|
|
12
|
+
recursive-include examples *.py
|
|
13
|
+
|
|
14
|
+
# Include tests
|
|
15
|
+
recursive-include tests *.py
|
|
16
|
+
|
|
17
|
+
# Exclude compiled files
|
|
18
|
+
global-exclude *.pyc
|
|
19
|
+
global-exclude __pycache__
|
|
20
|
+
global-exclude *.pyo
|
|
21
|
+
global-exclude .DS_Store
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ka9q-python
|
|
3
|
+
Version: 3.2.0
|
|
4
|
+
Summary: Python interface for ka9q-radio control and monitoring
|
|
5
|
+
Home-page: https://github.com/mijahauan/ka9q-python
|
|
6
|
+
Author: Michael Hauan AC0G
|
|
7
|
+
Author-email: Michael Hauan AC0G <ac0g@hauan.org>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/mijahauan/ka9q-python
|
|
10
|
+
Project-URL: Documentation, https://github.com/mijahauan/ka9q-python/blob/main/README.md
|
|
11
|
+
Project-URL: Repository, https://github.com/mijahauan/ka9q-python
|
|
12
|
+
Project-URL: Issues, https://github.com/mijahauan/ka9q-python/issues
|
|
13
|
+
Keywords: ka9q-radio,sdr,ham-radio,radio-control
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Intended Audience :: Telecommunications Industry
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Communications :: Ham Radio
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: numpy>=1.24.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
31
|
+
Dynamic: author
|
|
32
|
+
Dynamic: home-page
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
Dynamic: requires-python
|
|
35
|
+
|
|
36
|
+
# ka9q-python
|
|
37
|
+
|
|
38
|
+
[](https://badge.fury.io/py/ka9q-python)
|
|
39
|
+
[](https://opensource.org/licenses/MIT)
|
|
40
|
+
|
|
41
|
+
**General-purpose Python library for controlling [ka9q-radio](https://github.com/ka9q/ka9q-radio)**
|
|
42
|
+
|
|
43
|
+
Control radiod channels for any application: AM/FM/SSB radio, WSPR monitoring, SuperDARN radar, CODAR oceanography, HF fax, satellite downlinks, and more.
|
|
44
|
+
|
|
45
|
+
**Note:** Package name is `ka9q-python` out of respect for KA9Q (Phil Karn's callsign). Import as `import ka9q`.
|
|
46
|
+
|
|
47
|
+
## Table of Contents
|
|
48
|
+
|
|
49
|
+
- [Features](#features)
|
|
50
|
+
- [Installation](#installation)
|
|
51
|
+
- [Quick Start](#quick-start)
|
|
52
|
+
- [Documentation](#documentation)
|
|
53
|
+
- [Examples](#examples)
|
|
54
|
+
- [Use Cases](#use-cases)
|
|
55
|
+
- [License](#license)
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
✅ **Zero assumptions** - Works for any SDR application
|
|
60
|
+
✅ **Complete API** - All 85+ radiod parameters exposed
|
|
61
|
+
✅ **Channel control** - Create, configure, discover channels
|
|
62
|
+
✅ **RTP recording** - Generic recorder with timing support and state machine
|
|
63
|
+
✅ **Precise timing** - GPS_TIME/RTP_TIMESNAP for accurate timestamps
|
|
64
|
+
✅ **Multi-homed support** - Works on systems with multiple network interfaces
|
|
65
|
+
✅ **Pure Python** - No compiled dependencies
|
|
66
|
+
✅ **Well tested** - Comprehensive test coverage
|
|
67
|
+
✅ **Documented** - Comprehensive examples and API reference included
|
|
68
|
+
|
|
69
|
+
## Installation
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install ka9q-python
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Or install from source:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
git clone https://github.com/mijahauan/ka9q-python.git
|
|
79
|
+
cd ka9q-python
|
|
80
|
+
pip install -e .
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Quick Start
|
|
84
|
+
|
|
85
|
+
### Listen to AM Broadcast
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from ka9q import RadiodControl
|
|
89
|
+
|
|
90
|
+
# Connect to radiod
|
|
91
|
+
control = RadiodControl("radiod.local")
|
|
92
|
+
|
|
93
|
+
# Create AM channel on 10 MHz WWV
|
|
94
|
+
control.create_channel(
|
|
95
|
+
ssrc=10000000,
|
|
96
|
+
frequency_hz=10.0e6,
|
|
97
|
+
preset="am",
|
|
98
|
+
sample_rate=12000
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# RTP stream now available with SSRC 10000000
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Monitor WSPR Bands
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from ka9q import RadiodControl
|
|
108
|
+
|
|
109
|
+
control = RadiodControl("radiod.local")
|
|
110
|
+
|
|
111
|
+
wspr_bands = [
|
|
112
|
+
(1.8366e6, "160m"),
|
|
113
|
+
(3.5686e6, "80m"),
|
|
114
|
+
(7.0386e6, "40m"),
|
|
115
|
+
(10.1387e6, "30m"),
|
|
116
|
+
(14.0956e6, "20m"),
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
for freq, band in wspr_bands:
|
|
120
|
+
control.create_channel(
|
|
121
|
+
ssrc=int(freq),
|
|
122
|
+
frequency_hz=freq,
|
|
123
|
+
preset="usb",
|
|
124
|
+
sample_rate=12000
|
|
125
|
+
)
|
|
126
|
+
print(f"{band} WSPR channel created")
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Discover Existing Channels
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from ka9q import discover_channels
|
|
133
|
+
|
|
134
|
+
channels = discover_channels("radiod.local")
|
|
135
|
+
for ssrc, info in channels.items():
|
|
136
|
+
print(f"{ssrc}: {info.frequency/1e6:.3f} MHz, {info.preset}, {info.sample_rate} Hz")
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Record RTP Stream with Precise Timing
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from ka9q import discover_channels, RTPRecorder
|
|
143
|
+
import time
|
|
144
|
+
|
|
145
|
+
# Get channel with timing info
|
|
146
|
+
channels = discover_channels("radiod.local")
|
|
147
|
+
channel = channels[14074000]
|
|
148
|
+
|
|
149
|
+
# Define packet handler
|
|
150
|
+
def handle_packet(header, payload, wallclock):
|
|
151
|
+
print(f"Packet at {wallclock}: {len(payload)} bytes")
|
|
152
|
+
|
|
153
|
+
# Create and start recorder
|
|
154
|
+
recorder = RTPRecorder(channel=channel, on_packet=handle_packet)
|
|
155
|
+
recorder.start()
|
|
156
|
+
recorder.start_recording()
|
|
157
|
+
time.sleep(60) # Record for 60 seconds
|
|
158
|
+
recorder.stop_recording()
|
|
159
|
+
recorder.stop()
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Multi-Homed Systems
|
|
163
|
+
|
|
164
|
+
For systems with multiple network interfaces, specify which interface to use:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from ka9q import RadiodControl, discover_channels
|
|
168
|
+
|
|
169
|
+
# Specify your interface IP address
|
|
170
|
+
my_interface = "192.168.1.100"
|
|
171
|
+
|
|
172
|
+
# Create control with specific interface
|
|
173
|
+
control = RadiodControl("radiod.local", interface=my_interface)
|
|
174
|
+
|
|
175
|
+
# Discovery on specific interface
|
|
176
|
+
channels = discover_channels("radiod.local", interface=my_interface)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Documentation
|
|
180
|
+
|
|
181
|
+
For detailed information, please refer to the documentation in the `docs/` directory:
|
|
182
|
+
|
|
183
|
+
- **[API Reference](docs/API_REFERENCE.md)**: Full details on all classes, methods, and functions.
|
|
184
|
+
- **[RTP Timing Support](docs/RTP_TIMING_SUPPORT.md)**: Guide to RTP timing and synchronization.
|
|
185
|
+
- **[Architecture](docs/ARCHITECTURE.md)**: Overview of the library's design and structure.
|
|
186
|
+
- **[Installation Guide](docs/INSTALLATION.md)**: Detailed installation instructions.
|
|
187
|
+
- **[Testing Guide](docs/TESTING_GUIDE.md)**: Information on how to run the test suite.
|
|
188
|
+
- **[Security Considerations](docs/SECURITY.md)**: Important security information regarding the ka9q-radio protocol.
|
|
189
|
+
- **[Changelog](docs/CHANGELOG.md)**: A log of all changes for each version.
|
|
190
|
+
- **[Release Notes](docs/releases/)**: Release-specific notes and instructions.
|
|
191
|
+
|
|
192
|
+
## Examples
|
|
193
|
+
|
|
194
|
+
See the `examples/` directory for complete applications:
|
|
195
|
+
|
|
196
|
+
- **`discover_example.py`** - Channel discovery methods (native Python and control utility)
|
|
197
|
+
- **`tune.py`** - Interactive channel tuning utility (Python implementation of ka9q-radio's tune)
|
|
198
|
+
- **`tune_example.py`** - Programmatic examples of using the tune() method
|
|
199
|
+
- **`rtp_recorder_example.py`** - Complete RTP recorder with timing and state machine
|
|
200
|
+
- **`test_timing_fields.py`** - Verify GPS_TIME/RTP_TIMESNAP timing fields
|
|
201
|
+
- **`simple_am_radio.py`** - Minimal AM broadcast listener
|
|
202
|
+
- **`superdarn_recorder.py`** - Ionospheric radar monitoring
|
|
203
|
+
- **`codar_oceanography.py`** - Ocean current radar
|
|
204
|
+
- **`hf_band_scanner.py`** - Dynamic frequency scanner
|
|
205
|
+
- **`wspr_monitor.py`** - Weak signal propagation reporter
|
|
206
|
+
|
|
207
|
+
## Use Cases
|
|
208
|
+
|
|
209
|
+
### AM/FM/SSB Radio
|
|
210
|
+
- Broadcast monitoring
|
|
211
|
+
- Ham radio operation
|
|
212
|
+
- Shortwave listening
|
|
213
|
+
|
|
214
|
+
### Scientific Research
|
|
215
|
+
- WSPR propagation studies
|
|
216
|
+
- SuperDARN ionospheric radar
|
|
217
|
+
- CODAR ocean current mapping
|
|
218
|
+
- Meteor scatter
|
|
219
|
+
- EME (moonbounce)
|
|
220
|
+
|
|
221
|
+
### Digital Modes
|
|
222
|
+
- FT8/FT4 monitoring
|
|
223
|
+
- RTTY/PSK decoding
|
|
224
|
+
- DRM digital radio
|
|
225
|
+
- HF fax reception
|
|
226
|
+
|
|
227
|
+
### Satellite Operations
|
|
228
|
+
- Downlink reception
|
|
229
|
+
- Doppler tracking
|
|
230
|
+
- Multi-frequency monitoring
|
|
231
|
+
|
|
232
|
+
### Custom Applications
|
|
233
|
+
**No assumptions!** Use for anything SDR-related.
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# ka9q-python
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/ka9q-python)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
**General-purpose Python library for controlling [ka9q-radio](https://github.com/ka9q/ka9q-radio)**
|
|
7
|
+
|
|
8
|
+
Control radiod channels for any application: AM/FM/SSB radio, WSPR monitoring, SuperDARN radar, CODAR oceanography, HF fax, satellite downlinks, and more.
|
|
9
|
+
|
|
10
|
+
**Note:** Package name is `ka9q-python` out of respect for KA9Q (Phil Karn's callsign). Import as `import ka9q`.
|
|
11
|
+
|
|
12
|
+
## Table of Contents
|
|
13
|
+
|
|
14
|
+
- [Features](#features)
|
|
15
|
+
- [Installation](#installation)
|
|
16
|
+
- [Quick Start](#quick-start)
|
|
17
|
+
- [Documentation](#documentation)
|
|
18
|
+
- [Examples](#examples)
|
|
19
|
+
- [Use Cases](#use-cases)
|
|
20
|
+
- [License](#license)
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
✅ **Zero assumptions** - Works for any SDR application
|
|
25
|
+
✅ **Complete API** - All 85+ radiod parameters exposed
|
|
26
|
+
✅ **Channel control** - Create, configure, discover channels
|
|
27
|
+
✅ **RTP recording** - Generic recorder with timing support and state machine
|
|
28
|
+
✅ **Precise timing** - GPS_TIME/RTP_TIMESNAP for accurate timestamps
|
|
29
|
+
✅ **Multi-homed support** - Works on systems with multiple network interfaces
|
|
30
|
+
✅ **Pure Python** - No compiled dependencies
|
|
31
|
+
✅ **Well tested** - Comprehensive test coverage
|
|
32
|
+
✅ **Documented** - Comprehensive examples and API reference included
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install ka9q-python
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or install from source:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
git clone https://github.com/mijahauan/ka9q-python.git
|
|
44
|
+
cd ka9q-python
|
|
45
|
+
pip install -e .
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
### Listen to AM Broadcast
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from ka9q import RadiodControl
|
|
54
|
+
|
|
55
|
+
# Connect to radiod
|
|
56
|
+
control = RadiodControl("radiod.local")
|
|
57
|
+
|
|
58
|
+
# Create AM channel on 10 MHz WWV
|
|
59
|
+
control.create_channel(
|
|
60
|
+
ssrc=10000000,
|
|
61
|
+
frequency_hz=10.0e6,
|
|
62
|
+
preset="am",
|
|
63
|
+
sample_rate=12000
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# RTP stream now available with SSRC 10000000
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Monitor WSPR Bands
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from ka9q import RadiodControl
|
|
73
|
+
|
|
74
|
+
control = RadiodControl("radiod.local")
|
|
75
|
+
|
|
76
|
+
wspr_bands = [
|
|
77
|
+
(1.8366e6, "160m"),
|
|
78
|
+
(3.5686e6, "80m"),
|
|
79
|
+
(7.0386e6, "40m"),
|
|
80
|
+
(10.1387e6, "30m"),
|
|
81
|
+
(14.0956e6, "20m"),
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
for freq, band in wspr_bands:
|
|
85
|
+
control.create_channel(
|
|
86
|
+
ssrc=int(freq),
|
|
87
|
+
frequency_hz=freq,
|
|
88
|
+
preset="usb",
|
|
89
|
+
sample_rate=12000
|
|
90
|
+
)
|
|
91
|
+
print(f"{band} WSPR channel created")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Discover Existing Channels
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from ka9q import discover_channels
|
|
98
|
+
|
|
99
|
+
channels = discover_channels("radiod.local")
|
|
100
|
+
for ssrc, info in channels.items():
|
|
101
|
+
print(f"{ssrc}: {info.frequency/1e6:.3f} MHz, {info.preset}, {info.sample_rate} Hz")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Record RTP Stream with Precise Timing
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from ka9q import discover_channels, RTPRecorder
|
|
108
|
+
import time
|
|
109
|
+
|
|
110
|
+
# Get channel with timing info
|
|
111
|
+
channels = discover_channels("radiod.local")
|
|
112
|
+
channel = channels[14074000]
|
|
113
|
+
|
|
114
|
+
# Define packet handler
|
|
115
|
+
def handle_packet(header, payload, wallclock):
|
|
116
|
+
print(f"Packet at {wallclock}: {len(payload)} bytes")
|
|
117
|
+
|
|
118
|
+
# Create and start recorder
|
|
119
|
+
recorder = RTPRecorder(channel=channel, on_packet=handle_packet)
|
|
120
|
+
recorder.start()
|
|
121
|
+
recorder.start_recording()
|
|
122
|
+
time.sleep(60) # Record for 60 seconds
|
|
123
|
+
recorder.stop_recording()
|
|
124
|
+
recorder.stop()
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Multi-Homed Systems
|
|
128
|
+
|
|
129
|
+
For systems with multiple network interfaces, specify which interface to use:
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from ka9q import RadiodControl, discover_channels
|
|
133
|
+
|
|
134
|
+
# Specify your interface IP address
|
|
135
|
+
my_interface = "192.168.1.100"
|
|
136
|
+
|
|
137
|
+
# Create control with specific interface
|
|
138
|
+
control = RadiodControl("radiod.local", interface=my_interface)
|
|
139
|
+
|
|
140
|
+
# Discovery on specific interface
|
|
141
|
+
channels = discover_channels("radiod.local", interface=my_interface)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Documentation
|
|
145
|
+
|
|
146
|
+
For detailed information, please refer to the documentation in the `docs/` directory:
|
|
147
|
+
|
|
148
|
+
- **[API Reference](docs/API_REFERENCE.md)**: Full details on all classes, methods, and functions.
|
|
149
|
+
- **[RTP Timing Support](docs/RTP_TIMING_SUPPORT.md)**: Guide to RTP timing and synchronization.
|
|
150
|
+
- **[Architecture](docs/ARCHITECTURE.md)**: Overview of the library's design and structure.
|
|
151
|
+
- **[Installation Guide](docs/INSTALLATION.md)**: Detailed installation instructions.
|
|
152
|
+
- **[Testing Guide](docs/TESTING_GUIDE.md)**: Information on how to run the test suite.
|
|
153
|
+
- **[Security Considerations](docs/SECURITY.md)**: Important security information regarding the ka9q-radio protocol.
|
|
154
|
+
- **[Changelog](docs/CHANGELOG.md)**: A log of all changes for each version.
|
|
155
|
+
- **[Release Notes](docs/releases/)**: Release-specific notes and instructions.
|
|
156
|
+
|
|
157
|
+
## Examples
|
|
158
|
+
|
|
159
|
+
See the `examples/` directory for complete applications:
|
|
160
|
+
|
|
161
|
+
- **`discover_example.py`** - Channel discovery methods (native Python and control utility)
|
|
162
|
+
- **`tune.py`** - Interactive channel tuning utility (Python implementation of ka9q-radio's tune)
|
|
163
|
+
- **`tune_example.py`** - Programmatic examples of using the tune() method
|
|
164
|
+
- **`rtp_recorder_example.py`** - Complete RTP recorder with timing and state machine
|
|
165
|
+
- **`test_timing_fields.py`** - Verify GPS_TIME/RTP_TIMESNAP timing fields
|
|
166
|
+
- **`simple_am_radio.py`** - Minimal AM broadcast listener
|
|
167
|
+
- **`superdarn_recorder.py`** - Ionospheric radar monitoring
|
|
168
|
+
- **`codar_oceanography.py`** - Ocean current radar
|
|
169
|
+
- **`hf_band_scanner.py`** - Dynamic frequency scanner
|
|
170
|
+
- **`wspr_monitor.py`** - Weak signal propagation reporter
|
|
171
|
+
|
|
172
|
+
## Use Cases
|
|
173
|
+
|
|
174
|
+
### AM/FM/SSB Radio
|
|
175
|
+
- Broadcast monitoring
|
|
176
|
+
- Ham radio operation
|
|
177
|
+
- Shortwave listening
|
|
178
|
+
|
|
179
|
+
### Scientific Research
|
|
180
|
+
- WSPR propagation studies
|
|
181
|
+
- SuperDARN ionospheric radar
|
|
182
|
+
- CODAR ocean current mapping
|
|
183
|
+
- Meteor scatter
|
|
184
|
+
- EME (moonbounce)
|
|
185
|
+
|
|
186
|
+
### Digital Modes
|
|
187
|
+
- FT8/FT4 monitoring
|
|
188
|
+
- RTTY/PSK decoding
|
|
189
|
+
- DRM digital radio
|
|
190
|
+
- HF fax reception
|
|
191
|
+
|
|
192
|
+
### Satellite Operations
|
|
193
|
+
- Downlink reception
|
|
194
|
+
- Doppler tracking
|
|
195
|
+
- Multi-frequency monitoring
|
|
196
|
+
|
|
197
|
+
### Custom Applications
|
|
198
|
+
**No assumptions!** Use for anything SDR-related.
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Demonstration of newly exposed radiod features in ka9q-python
|
|
4
|
+
|
|
5
|
+
This script demonstrates the use of advanced radiod features that
|
|
6
|
+
were previously not exposed in the Python interface.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from ka9q.control import RadiodControl
|
|
10
|
+
from ka9q.types import Encoding
|
|
11
|
+
|
|
12
|
+
def main():
|
|
13
|
+
# Connect to radiod
|
|
14
|
+
control = RadiodControl(control_address="239.101.6.1")
|
|
15
|
+
|
|
16
|
+
# Example SSRC (replace with your actual channel SSRC)
|
|
17
|
+
ssrc = 12345
|
|
18
|
+
|
|
19
|
+
print("=== Advanced RadioD Feature Demonstrations ===\n")
|
|
20
|
+
|
|
21
|
+
# 1. Doppler tracking for satellite reception
|
|
22
|
+
print("1. Setting Doppler shift and rate (for satellite tracking)")
|
|
23
|
+
control.set_doppler(ssrc=ssrc, doppler_hz=-5000, doppler_rate_hz_per_sec=100)
|
|
24
|
+
print(" ✓ Doppler: -5 kHz, rate: 100 Hz/s\n")
|
|
25
|
+
|
|
26
|
+
# 2. PLL configuration for carrier tracking
|
|
27
|
+
print("2. Configuring PLL for coherent AM detection")
|
|
28
|
+
control.set_pll(ssrc=ssrc, enable=True, bandwidth_hz=50, square=False)
|
|
29
|
+
print(" ✓ PLL enabled with 50 Hz bandwidth\n")
|
|
30
|
+
|
|
31
|
+
# 3. SNR squelch
|
|
32
|
+
print("3. Setting SNR-based squelch")
|
|
33
|
+
control.set_squelch(ssrc=ssrc, enable=True, open_snr_db=10, close_snr_db=8)
|
|
34
|
+
print(" ✓ Squelch opens at 10 dB, closes at 8 dB\n")
|
|
35
|
+
|
|
36
|
+
# 4. Independent Sideband mode
|
|
37
|
+
print("4. Enabling Independent Sideband (ISB) mode")
|
|
38
|
+
control.set_independent_sideband(ssrc=ssrc, enable=True)
|
|
39
|
+
control.set_output_channels(ssrc=ssrc, channels=2)
|
|
40
|
+
print(" ✓ ISB mode enabled (USB/LSB to L/R channels)\n")
|
|
41
|
+
|
|
42
|
+
# 5. Secondary filter configuration
|
|
43
|
+
print("5. Configuring secondary filter for extra selectivity")
|
|
44
|
+
control.set_filter2(ssrc=ssrc, blocksize=5, kaiser_beta=3.5)
|
|
45
|
+
print(" ✓ Filter2 configured with blocksize=5, beta=3.5\n")
|
|
46
|
+
|
|
47
|
+
# 6. Opus encoder settings
|
|
48
|
+
print("6. Setting Opus encoding and bitrate")
|
|
49
|
+
control.set_output_encoding(ssrc=ssrc, encoding=Encoding.OPUS)
|
|
50
|
+
control.set_opus_bitrate(ssrc=ssrc, bitrate=64000)
|
|
51
|
+
print(" ✓ Opus encoding at 64 kbps\n")
|
|
52
|
+
|
|
53
|
+
# 7. Spectrum analyzer mode
|
|
54
|
+
print("7. Configuring spectrum analyzer mode")
|
|
55
|
+
control.set_spectrum(ssrc=ssrc, bin_bw_hz=100, bin_count=512, kaiser_beta=6.0)
|
|
56
|
+
print(" ✓ Spectrum mode: 100 Hz bins, 512 bins, beta=6.0\n")
|
|
57
|
+
|
|
58
|
+
# 8. Packet buffering control
|
|
59
|
+
print("8. Setting packet buffering for lower packet rate")
|
|
60
|
+
control.set_packet_buffering(ssrc=ssrc, min_blocks=2)
|
|
61
|
+
print(" ✓ Minimum 2 blocks (40ms) buffering\n")
|
|
62
|
+
|
|
63
|
+
# 9. Status interval configuration
|
|
64
|
+
print("9. Configuring automatic status reporting")
|
|
65
|
+
control.set_status_interval(ssrc=ssrc, interval=50)
|
|
66
|
+
print(" ✓ Status sent every 50 frames\n")
|
|
67
|
+
|
|
68
|
+
# 10. RF hardware controls (hardware-dependent)
|
|
69
|
+
print("10. Adjusting RF gain and attenuation")
|
|
70
|
+
# control.set_rf_gain(ssrc=ssrc, gain_db=20)
|
|
71
|
+
# control.set_rf_attenuation(ssrc=ssrc, atten_db=10)
|
|
72
|
+
print(" ✓ RF controls available (commented out - hardware dependent)\n")
|
|
73
|
+
|
|
74
|
+
# 11. AGC threshold (separate from existing AGC settings)
|
|
75
|
+
print("11. Setting AGC threshold")
|
|
76
|
+
control.set_agc_threshold(ssrc=ssrc, threshold_db=10)
|
|
77
|
+
print(" ✓ AGC threshold at 10 dB above noise\n")
|
|
78
|
+
|
|
79
|
+
# 12. First LO tuning (affects all channels - use with care!)
|
|
80
|
+
print("12. Setting first LO frequency")
|
|
81
|
+
# control.set_first_lo(ssrc=ssrc, frequency_hz=14.1e6)
|
|
82
|
+
print(" ✓ First LO tuning available (commented out - affects all channels)\n")
|
|
83
|
+
|
|
84
|
+
# 13. FM-specific features
|
|
85
|
+
print("13. FM threshold extension (for weak signals)")
|
|
86
|
+
control.set_fm_threshold_extension(ssrc=ssrc, enable=True)
|
|
87
|
+
print(" ✓ FM threshold extension enabled\n")
|
|
88
|
+
|
|
89
|
+
# 14. Linear mode envelope detection
|
|
90
|
+
print("14. Enabling envelope detection (for AM)")
|
|
91
|
+
control.set_envelope_detection(ssrc=ssrc, enable=True)
|
|
92
|
+
print(" ✓ Envelope detection enabled\n")
|
|
93
|
+
|
|
94
|
+
# 15. Demodulator type switching
|
|
95
|
+
print("15. Changing demodulator type")
|
|
96
|
+
# control.set_demod_type(ssrc=ssrc, demod_type=1) # 0=LINEAR, 1=FM, 2=WFM, 3=SPECTRUM
|
|
97
|
+
print(" ✓ Demod type switching available (commented out)\n")
|
|
98
|
+
|
|
99
|
+
# 16. Output destination
|
|
100
|
+
print("16. Setting RTP output destination")
|
|
101
|
+
# control.set_destination(ssrc=ssrc, address="239.1.2.3", port=5004)
|
|
102
|
+
print(" ✓ Destination control available (commented out)\n")
|
|
103
|
+
|
|
104
|
+
# 17. Option bits (experimental/debug)
|
|
105
|
+
print("17. Setting option bits")
|
|
106
|
+
# control.set_options(ssrc=ssrc, set_bits=0x01, clear_bits=0x02)
|
|
107
|
+
print(" ✓ Option bit control available (commented out - experimental)\n")
|
|
108
|
+
|
|
109
|
+
print("\n=== All features demonstrated! ===")
|
|
110
|
+
print("Note: Some features are commented out to prevent unintended changes.")
|
|
111
|
+
print("Uncomment and adjust as needed for your specific use case.")
|
|
112
|
+
|
|
113
|
+
control.close()
|
|
114
|
+
|
|
115
|
+
if __name__ == "__main__":
|
|
116
|
+
main()
|