ka9q-python 3.9.0__tar.gz → 3.12.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.
Files changed (179) hide show
  1. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/CHANGELOG.md +77 -0
  2. {ka9q_python-3.9.0/ka9q_python.egg-info → ka9q_python-3.12.0}/PKG-INFO +38 -61
  3. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/README.md +37 -60
  4. ka9q_python-3.12.0/docs/API_REFERENCE.md +936 -0
  5. ka9q_python-3.12.0/docs/ARCHITECTURE.md +376 -0
  6. ka9q_python-3.12.0/docs/CLI_GUIDE.md +288 -0
  7. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/docs/GETTING_STARTED.md +20 -6
  8. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/docs/INSTALLATION.md +34 -14
  9. ka9q_python-3.12.0/docs/MULTI_STREAM.md +280 -0
  10. ka9q_python-3.12.0/docs/RECIPES.md +695 -0
  11. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/docs/RTP_TIMING_SUPPORT.md +31 -59
  12. ka9q_python-3.12.0/docs/SECURITY.md +54 -0
  13. ka9q_python-3.12.0/docs/TESTING_GUIDE.md +199 -0
  14. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/docs/TUI_GUIDE.md +28 -7
  15. ka9q_python-3.12.0/examples/spectrum_example.py +109 -0
  16. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/__init__.py +5 -1
  17. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/cli.py +4 -2
  18. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/compat.py +1 -1
  19. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/control.py +166 -12
  20. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/multi_stream.py +10 -0
  21. ka9q_python-3.12.0/ka9q/spectrum_stream.py +317 -0
  22. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/status.py +51 -3
  23. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/tui.py +256 -14
  24. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/types.py +2 -1
  25. {ka9q_python-3.9.0 → ka9q_python-3.12.0/ka9q_python.egg-info}/PKG-INFO +38 -61
  26. ka9q_python-3.12.0/ka9q_python.egg-info/SOURCES.txt +101 -0
  27. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q_radio_compat +1 -1
  28. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/pyproject.toml +1 -1
  29. ka9q_python-3.12.0/scripts/check_upstream_drift.py +490 -0
  30. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/setup.py +1 -1
  31. ka9q_python-3.12.0/tests/conftest.py +29 -0
  32. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_channel_verification.py +1 -5
  33. ka9q_python-3.12.0/tests/test_decode_description.py +46 -0
  34. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_encode_socket.py +41 -51
  35. ka9q_python-3.12.0/tests/test_filter_edges.py +256 -0
  36. ka9q_python-3.12.0/tests/test_lifetime.py +175 -0
  37. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_native_discovery.py +4 -1
  38. ka9q_python-3.12.0/tests/test_spectrum.py +271 -0
  39. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_tune_debug.py +3 -2
  40. ka9q_python-3.12.0/tests/test_upstream_drift.py +176 -0
  41. ka9q_python-3.9.0/RELEASE_NOTES_v3.5.0.md +0 -75
  42. ka9q_python-3.9.0/docs/API_REFERENCE.md +0 -1438
  43. ka9q_python-3.9.0/docs/ARCHITECTURE.md +0 -534
  44. ka9q_python-3.9.0/docs/CHANGELOG.md +0 -378
  45. ka9q_python-3.9.0/docs/CROSS_PLATFORM_SUPPORT.md +0 -251
  46. ka9q_python-3.9.0/docs/DISTRIBUTION_RECOMMENDATION.md +0 -343
  47. ka9q_python-3.9.0/docs/MULTI_HOMED_QUICK_REF.md +0 -305
  48. ka9q_python-3.9.0/docs/NATIVE_DISCOVERY.md +0 -276
  49. ka9q_python-3.9.0/docs/PYPI_PUBLICATION_GUIDE.md +0 -404
  50. ka9q_python-3.9.0/docs/QUICK_REFERENCE.md +0 -233
  51. ka9q_python-3.9.0/docs/RTP_RECORDER_PASS_ALL_PACKETS.md +0 -512
  52. ka9q_python-3.9.0/docs/RTP_TIMING_IMPLEMENTATION.md +0 -439
  53. ka9q_python-3.9.0/docs/SECURITY.md +0 -876
  54. ka9q_python-3.9.0/docs/SSRC_COLLISION_PREVENTION.md +0 -1000
  55. ka9q_python-3.9.0/docs/TESTING_GUIDE.md +0 -347
  56. ka9q_python-3.9.0/docs/TESTING_SUMMARY.md +0 -133
  57. ka9q_python-3.9.0/docs/TEST_RESULTS.md +0 -262
  58. ka9q_python-3.9.0/docs/WEB_UI_ENHANCEMENT_GUIDE.md +0 -412
  59. ka9q_python-3.9.0/docs/WEB_UI_ENHANCEMENT_IMPLEMENTED.md +0 -184
  60. ka9q_python-3.9.0/docs/WEB_UI_ESCAPE_SEQUENCE_FIX.md +0 -78
  61. ka9q_python-3.9.0/docs/WEB_UI_FUNCTIONALITY_REVIEW.md +0 -355
  62. ka9q_python-3.9.0/docs/WEB_UI_IMPLEMENTATION_STATUS.md +0 -356
  63. ka9q_python-3.9.0/docs/WEB_UI_INTERACTIVE_COMPLETE.md +0 -333
  64. ka9q_python-3.9.0/docs/development/CHANGES_SUMMARY.md +0 -304
  65. ka9q_python-3.9.0/docs/development/CHANNEL_CLEANUP_ADDITION.md +0 -136
  66. ka9q_python-3.9.0/docs/development/CHANNEL_CLEANUP_COMPLETE.md +0 -224
  67. ka9q_python-3.9.0/docs/development/CHANNEL_TUNING_DIAGNOSTICS.md +0 -495
  68. ka9q_python-3.9.0/docs/development/CODE_REVIEW_RECOMMENDATIONS.md +0 -456
  69. ka9q_python-3.9.0/docs/development/CODE_REVIEW_SUMMARY.md +0 -318
  70. ka9q_python-3.9.0/docs/development/COMMIT_SUMMARY.md +0 -212
  71. ka9q_python-3.9.0/docs/development/CRITICAL_FIXES_CHECKLIST.md +0 -295
  72. ka9q_python-3.9.0/docs/development/FINAL_SUMMARY.md +0 -469
  73. ka9q_python-3.9.0/docs/development/FIXES_SUMMARY.md +0 -89
  74. ka9q_python-3.9.0/docs/development/GIT_STATUS_SUMMARY.md +0 -109
  75. ka9q_python-3.9.0/docs/development/IMPLEMENTATION_COMPLETE.md +0 -441
  76. ka9q_python-3.9.0/docs/development/IMPLEMENTATION_STATUS.md +0 -444
  77. ka9q_python-3.9.0/docs/development/IMPLEMENTATION_SUMMARY.md +0 -70
  78. ka9q_python-3.9.0/docs/development/IMPLEMENTATION_SUMMARY_v2.2.0.md +0 -348
  79. ka9q_python-3.9.0/docs/development/IMPROVEMENTS_IMPLEMENTED.md +0 -454
  80. ka9q_python-3.9.0/docs/development/MULTI_HOMED_ACTION_PLAN.md +0 -304
  81. ka9q_python-3.9.0/docs/development/MULTI_HOMED_IMPLEMENTATION_COMPLETE.md +0 -330
  82. ka9q_python-3.9.0/docs/development/MULTI_HOMED_SUPPORT_REVIEW.md +0 -471
  83. ka9q_python-3.9.0/docs/development/PACKAGE_STATUS.md +0 -257
  84. ka9q_python-3.9.0/docs/development/PACKAGE_VERIFICATION.md +0 -238
  85. ka9q_python-3.9.0/docs/development/PERFORMANCE_FIXES_APPLIED.md +0 -428
  86. ka9q_python-3.9.0/docs/development/PERFORMANCE_REVIEW.md +0 -762
  87. ka9q_python-3.9.0/docs/development/PERFORMANCE_REVIEW_V2.md +0 -776
  88. ka9q_python-3.9.0/docs/development/PERFORMANCE_SUMMARY.md +0 -203
  89. ka9q_python-3.9.0/docs/development/QUICK_ACTION_ITEMS.md +0 -370
  90. ka9q_python-3.9.0/docs/development/QUICK_START_DIAGNOSIS.md +0 -319
  91. ka9q_python-3.9.0/docs/development/RELEASE_CHECKLIST_v3.0.0.md +0 -133
  92. ka9q_python-3.9.0/docs/development/SUMMARY.md +0 -291
  93. ka9q_python-3.9.0/docs/development/SUMMARY_WEB_UI_FIXES.md +0 -153
  94. ka9q_python-3.9.0/docs/development/TUNE_IMPLEMENTATION.md +0 -291
  95. ka9q_python-3.9.0/docs/development/WEBUI_SUMMARY.md +0 -411
  96. ka9q_python-3.9.0/docs/development/WEB_UI_ENHANCEMENTS_COMPLETE.md +0 -198
  97. ka9q_python-3.9.0/docs/features/CONTROL_COMPARISON.md +0 -201
  98. ka9q_python-3.9.0/docs/features/DESTINATION_AWARE_CHANNELS.md +0 -73
  99. ka9q_python-3.9.0/docs/features/NEW_FEATURES.md +0 -239
  100. ka9q_python-3.9.0/docs/features/RADIOD_FEATURES_SUMMARY.md +0 -261
  101. ka9q_python-3.9.0/docs/features/RTP_DESTINATION_FEATURE.md +0 -237
  102. ka9q_python-3.9.0/docs/releases/GITHUB_RELEASE_INSTRUCTIONS.md +0 -196
  103. ka9q_python-3.9.0/docs/releases/GITHUB_RELEASE_v2.2.0.md +0 -275
  104. ka9q_python-3.9.0/docs/releases/GITHUB_RELEASE_v2.4.0.md +0 -269
  105. ka9q_python-3.9.0/docs/releases/GITHUB_RELEASE_v2.5.0.md +0 -241
  106. ka9q_python-3.9.0/docs/releases/GITHUB_RELEASE_v3.0.0.md +0 -148
  107. ka9q_python-3.9.0/docs/releases/GITHUB_RELEASE_v3.1.0.md +0 -139
  108. ka9q_python-3.9.0/docs/releases/GITHUB_RELEASE_v3.2.0.md +0 -116
  109. ka9q_python-3.9.0/docs/releases/RELEASE_NOTES.md +0 -244
  110. ka9q_python-3.9.0/docs/releases/RELEASE_NOTES_v2.1.0.md +0 -291
  111. ka9q_python-3.9.0/docs/releases/RELEASE_NOTES_v2.2.0.md +0 -554
  112. ka9q_python-3.9.0/docs/releases/RELEASE_NOTES_v2.3.0.md +0 -297
  113. ka9q_python-3.9.0/docs/releases/RELEASE_NOTES_v2.4.0.md +0 -545
  114. ka9q_python-3.9.0/docs/releases/RTP_TIMING_RELEASE_NOTES.md +0 -281
  115. ka9q_python-3.9.0/ka9q_python.egg-info/SOURCES.txt +0 -160
  116. ka9q_python-3.9.0/tests/conftest.py +0 -14
  117. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/LICENSE +0 -0
  118. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/MANIFEST.in +0 -0
  119. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/advanced_features_demo.py +0 -0
  120. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/channel_cleanup_example.py +0 -0
  121. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/codar_oceanography.py +0 -0
  122. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/diagnostics/diagnose_packets.py +0 -0
  123. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/diagnostics/repro_utc_bug.py +0 -0
  124. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/discover_example.py +0 -0
  125. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/grape_integration_example.py +0 -0
  126. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/hf_band_scanner.py +0 -0
  127. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/multi_stream_smoke.py +0 -0
  128. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/rtp_recorder_example.py +0 -0
  129. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/simple_am_radio.py +0 -0
  130. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/stream_example.py +0 -0
  131. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/superdarn_recorder.py +0 -0
  132. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/test_channel_operations.py +0 -0
  133. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/test_improvements.py +0 -0
  134. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/test_timing_fields.py +0 -0
  135. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/tune.py +0 -0
  136. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/examples/tune_example.py +0 -0
  137. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/addressing.py +0 -0
  138. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/discovery.py +0 -0
  139. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/exceptions.py +0 -0
  140. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/managed_stream.py +0 -0
  141. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/monitor.py +0 -0
  142. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/pps_calibrator.py +0 -0
  143. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/resequencer.py +0 -0
  144. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/rtp_recorder.py +0 -0
  145. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/stream.py +0 -0
  146. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/stream_quality.py +0 -0
  147. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q/utils.py +0 -0
  148. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q_python.egg-info/dependency_links.txt +0 -0
  149. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q_python.egg-info/entry_points.txt +0 -0
  150. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q_python.egg-info/requires.txt +0 -0
  151. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/ka9q_python.egg-info/top_level.txt +0 -0
  152. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/scripts/sync_types.py +0 -0
  153. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/setup.cfg +0 -0
  154. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/__init__.py +0 -0
  155. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_addressing.py +0 -0
  156. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_create_split_encoding.py +0 -0
  157. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_decode_functions.py +0 -0
  158. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_encode_functions.py +0 -0
  159. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_ensure_channel_encoding.py +0 -0
  160. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_integration.py +0 -0
  161. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_iq_20khz_f32.py +0 -0
  162. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_listen_multicast.py +0 -0
  163. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_managed_stream_recovery.py +0 -0
  164. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_monitor.py +0 -0
  165. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_multihomed.py +0 -0
  166. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_performance_fixes.py +0 -0
  167. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_protocol_compat.py +0 -0
  168. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_remove_channel.py +0 -0
  169. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_rtp_recorder.py +0 -0
  170. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_security_features.py +0 -0
  171. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_ssrc_dest_unit.py +0 -0
  172. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_ssrc_encoding_unit.py +0 -0
  173. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_ssrc_radiod_host_unit.py +0 -0
  174. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_status_decoder.py +0 -0
  175. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_ttl_warning.py +0 -0
  176. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_tune.py +0 -0
  177. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_tune_cli.py +0 -0
  178. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_tune_live.py +0 -0
  179. {ka9q_python-3.9.0 → ka9q_python-3.12.0}/tests/test_tune_method.py +0 -0
@@ -1,5 +1,82 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.12.0] - 2026-05-07
4
+
5
+ ### Added
6
+
7
+ - **Spectrum bin vector decoding**: `decode_status_packet()` now decodes `BIN_DATA` (float32, `SPECT_DEMOD`) and `BIN_BYTE_DATA` (uint8, `SPECT2_DEMOD`) TLV vectors from radiod status packets. New fields on `SpectrumStatus`:
8
+ - `bin_data: Optional[np.ndarray]` — float32 power values per FFT bin.
9
+ - `bin_byte_data: Optional[np.ndarray]` — uint8 quantised log-power values.
10
+ - `bin_power_db` property — returns dB values regardless of source format (10*log10 for float data, `base + byte * step` for byte data).
11
+
12
+ - **`SpectrumStream`**: new class for receiving real-time FFT spectrum data from radiod. Spectrum data flows over the status multicast channel (port 5006) as TLV vectors, not over RTP. `SpectrumStream` handles channel creation, periodic polling, SSRC filtering, and delivers decoded `ChannelStatus` objects (with populated `spectrum.bin_power_db`) to an `on_spectrum` callback. Supports retuning via `set_frequency()` and context manager usage.
13
+
14
+ ### Documentation
15
+
16
+ - API_REFERENCE.md: SpectrumStream section, SpectrumStatus bin vector fields, quickstart table updated.
17
+ - ARCHITECTURE.md: module listing, abstraction layer description, threading model updated.
18
+ - RECIPES.md: Recipe 5 covering spectrum display, spectrogram accumulation, frequency axis reconstruction, FFT parameter tuning, and combined audio+spectrum patterns.
19
+ - New `examples/spectrum_example.py`: runnable CLI example for real-time spectrum reception.
20
+
21
+ ### Tests
22
+
23
+ - 13 new unit tests in `tests/test_spectrum.py` covering float32 and uint8 bin decoding, multi-byte TLV lengths, `bin_power_db` property, combined metadata+bins, edge cases, and import verification.
24
+
25
+ ---
26
+
27
+
28
+ ## [3.11.0] - 2026-05-06
29
+
30
+ ### Added
31
+
32
+ - **Channel filter overrides on create / ensure / add_channel**: optional `low_edge`, `high_edge`, and `kaiser_beta` kwargs on `RadiodControl.create_channel()`, `RadiodControl.ensure_channel()`, and `MultiStream.add_channel()` — when specified, the requested filter passband is applied inline with the channel-create command (no transient at preset BW), and on the reuse path of `ensure_channel`, `set_filter` is called so the requested edges are authoritative regardless of the channel's prior state. Previously, callers were stuck with the preset's `low`/`high` values and had to either author a custom radiod preset or call `set_filter` manually after channel creation. Filter edges are not part of the SSRC hash — multiple callers requesting the same channel with different filters reconfigure last-writer-wins, matching the existing model for `gain` / `agc_enable`.
33
+ - Motivating clients: hf-timestd's BPSK PPS calibrator needs ~±500 Hz to match the TS1 injector's effectively-CW spectrum (the iq preset's ±5 kHz is wrong by an order of magnitude); planned SuperDARN and CODAR-sounder receivers need wider passbands than any single preset provides.
34
+
35
+ ### Backward Compatibility
36
+
37
+ - Default behavior unchanged: omitting all three kwargs produces a wire packet with no LOW_EDGE / HIGH_EDGE / KAISER_BETA tags, so radiod uses the preset's defaults exactly as before. Reuse path also skips `set_filter` when no filter args are supplied.
38
+
39
+ ### Tests
40
+
41
+ - 8 new unit tests in `tests/test_filter_edges.py` cover encode-presence on each entry point, encode-absence when omitted, ensure_channel forwarding on the create path, and ensure_channel reuse-path calling set_filter (only when filter args are supplied).
42
+
43
+ ---
44
+
45
+ ## [3.10.0] - 2026-04-30
46
+
47
+ ### Added
48
+
49
+ - **Channel-lifetime keep-alive** (radiod 0f8b622+): support for ka9q-radio's new self-destruct timer, which lets a channel declare a lifetime in radiod main-loop frames (~50 Hz at the default 20 ms blocktime); 0 means infinite, >0 decrements every frame and destroys the channel at zero. This gives crash-resilient cleanup — if a client dies, its channels expire on their own instead of lingering on radiod.
50
+ - `RadiodControl.set_channel_lifetime(ssrc, lifetime)` — explicit poll that sends the LIFETIME tag, suitable as a periodic keep-alive.
51
+ - `RadiodControl.create_channel(..., lifetime=None)` — optional kwarg; sends LIFETIME on the creation packet when provided.
52
+ - `RadiodControl.ensure_channel(..., lifetime=None)` — passes through to `create_channel`; on the reuse path, calls `set_channel_lifetime` so the value is enforced regardless of the channel's prior state.
53
+ - `RadiodControl.tune(..., lifetime=None)` — optional kwarg; LIFETIME is included in the multi-parameter command buffer.
54
+ - `_decode_status_response()` exposes received LIFETIME as `status['lifetime']`; `ChannelStatus.lifetime` field.
55
+ - **`StatusType.LIFETIME = 117`** in `ka9q/types.py` (synced from ka9q-radio commit `5498aef`).
56
+ - **`StatusType.DESCRIPTION` decode** in `_decode_status_response()`: incoming front-end / channel description strings are now surfaced as `status['description']` (the encode side already existed via `set_description`).
57
+
58
+ ### Backward Compatibility
59
+
60
+ - Default behavior unchanged: omitting `lifetime` produces a wire packet with no LIFETIME tag, so pre-`0f8b622` radiod stays compatible and existing clients see no change. Channels created without LIFETIME inherit radiod's template default (0 = infinite) and live until destroyed.
61
+
62
+ ### Tests
63
+
64
+ - 10 new unit tests in `tests/test_lifetime.py` cover encode-presence on each entry point, encode-absence when omitted, and validation of negative / non-int inputs.
65
+ - Refreshed stale `tests/test_encode_socket.py` to match the current 6-byte wire format that radiod's `decode_socket()` actually expects.
66
+ - Hardened `tests/test_native_discovery.py::test_native_discovery_with_valid_packet` to mock `RadiodControl._connect`, removing the DNS dependency on `test.local`.
67
+
68
+ ---
69
+
70
+ ## [3.9.0] - 2026-04-15
71
+
72
+ ### Added
73
+
74
+ - **`ka9q` CLI** (`ka9q/cli.py`): new console entry point `ka9q` (declared via `[project.scripts]`), exposing channel discovery, tune, create, destroy, and status commands against a running radiod.
75
+ - **Textual TUI** (`ka9q/tui.py`): an interactive Textual app for browsing channels and tuning interactively, with radiod and SSRC pickers. Optional install via `pip install ka9q-python[tui]`.
76
+ - **Typed `ChannelStatus` decoder** (`ka9q/status.py`): a typed dataclass view over the dict returned by `_decode_status_response`, so callers can use attribute access and IDE-completable fields instead of dict keys.
77
+
78
+ ---
79
+
3
80
  ## [3.8.0] - 2026-04-12
4
81
 
5
82
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ka9q-python
3
- Version: 3.9.0
3
+ Version: 3.12.0
4
4
  Summary: Python interface for ka9q-radio control and monitoring
5
5
  Home-page: https://github.com/mijahauan/ka9q-python
6
6
  Author: Michael Hauan AC0G
@@ -60,15 +60,15 @@ Control radiod channels for any application: AM/FM/SSB radio, WSPR monitoring, S
60
60
 
61
61
  ## Features
62
62
 
63
- **Zero assumptions** - Works for any SDR application
64
- **Complete API** - All 85+ radiod parameters exposed
65
- **Channel control** - Create, configure, discover channels
66
- **RTP recording** - Generic recorder with timing support and state machine
67
- **Precise timing** - GPS_TIME/RTP_TIMESNAP for accurate timestamps
68
- **Multi-homed support** - Works on systems with multiple network interfaces
69
- **Pure Python** - No compiled dependencies
70
- **Well tested** - Comprehensive test coverage
71
- **Documented** - Comprehensive examples and API reference included
63
+ - **Complete radiod API** all 110+ TLV status/command parameters exposed, generated from ka9q-radio's C headers
64
+ - **Four stream abstractions** `RTPRecorder` (raw packets), `RadiodStream` (samples + gap handling), `ManagedStream` (self-healing single channel), `MultiStream` (shared socket, many SSRCs)
65
+ - **Typed status decoder** `ChannelStatus`, `FrontendStatus`, `PllStatus`, etc. with dotted-path field access
66
+ - **Precise RTP timing** GPS_TIME / RTP_TIMESNAP for sample-accurate wallclock timestamps
67
+ - **LAN discovery** enumerate radiod instances and their active channels via mDNS
68
+ - **CLI + TUI** `ka9q list / query / set / tui` for interactive and scripted control
69
+ - **Multi-homed** explicit interface selection for hosts with multiple NICs
70
+ - **Protocol drift detection** — pinned to a specific ka9q-radio commit, with a sync script
71
+ - **Pure Python** NumPy is the only runtime dependency
72
72
 
73
73
  ## Installation
74
74
 
@@ -215,6 +215,7 @@ monitor.monitor_channel(
215
215
  preset="usb",
216
216
  sample_rate=12000
217
217
  )
218
+ ```
218
219
 
219
220
  ### Channel Cleanup (frequency = 0)
220
221
 
@@ -293,63 +294,39 @@ It auto-skips if `../ka9q-radio` is not present, so CI environments without the
293
294
 
294
295
  ## Documentation
295
296
 
296
- For detailed information, please refer to the documentation in the `docs/` directory:
297
-
298
- - **[API Reference](docs/API_REFERENCE.md)**: Full details on all classes, methods, and functions.
299
- - **[TUI Guide](docs/TUI_GUIDE.md)**: Launching and using the `ka9q tui` Textual terminal UI.
300
- - **[RTP Timing Support](docs/RTP_TIMING_SUPPORT.md)**: Guide to RTP timing and synchronization.
301
- - **[Architecture](docs/ARCHITECTURE.md)**: Overview of the library's design and structure.
302
- - **[Installation Guide](docs/INSTALLATION.md)**: Detailed installation instructions.
303
- - **[Testing Guide](docs/TESTING_GUIDE.md)**: Information on how to run the test suite.
304
- - **[Security Considerations](docs/SECURITY.md)**: Important security information regarding the ka9q-radio protocol.
305
- - **[Changelog](docs/CHANGELOG.md)**: A log of all changes for each version.
306
- - **[Release Notes](docs/releases/)**: Release-specific notes and instructions.
297
+ - **[Getting Started](docs/GETTING_STARTED.md)** first-run walkthrough
298
+ - **[Recipes](docs/RECIPES.md)** — task-oriented cookbook: LAN probing, fixed-channel pipelines (WSPR/PSK/FT8/timing), nimble SWL-style retuning, and using ka9q-python across different SDRs
299
+ - **[API Reference](docs/API_REFERENCE.md)** every public class, method, and function
300
+ - **[Architecture](docs/ARCHITECTURE.md)** module layout, threading, protocol
301
+ - **[CLI Guide](docs/CLI_GUIDE.md)** `ka9q list / query / set / tui` command reference
302
+ - **[TUI Guide](docs/TUI_GUIDE.md)** the Textual terminal UI
303
+ - **[MultiStream Guide](docs/MULTI_STREAM.md)** shared-socket multi-channel receiver
304
+ - **[RTP Timing](docs/RTP_TIMING_SUPPORT.md)** GPS_TIME / RTP_TIMESNAP for sample-accurate timestamps
305
+ - **[Installation](docs/INSTALLATION.md)** · **[Testing](docs/TESTING_GUIDE.md)** · **[Security](docs/SECURITY.md)**
306
+ - **[Changelog](CHANGELOG.md)**
307
307
 
308
308
  ## Examples
309
309
 
310
- See the `examples/` directory for complete applications:
311
-
312
- - **High-Level API**: `ensure_channel()` handles the complexity of checking existing channels, creating new ones only when necessary, and verifying configurations.
313
- - **Destination-Aware Channels**: Support for unique per-application multicast destinations and deterministic IP generation.
314
- - **Stream Sharing**: Deterministic SSRC allocation allows multiple independent applications to share `radiod` streams efficiently.
315
- - **`discover_example.py`** - Channel discovery methods (native Python and control utility)
316
- - **`tune.py`** - Interactive channel tuning utility (Python implementation of ka9q-radio's tune)
317
- - **`tune_example.py`** - Programmatic examples of using the tune() method
318
- - **`rtp_recorder_example.py`** - Complete RTP recorder with timing and state machine
319
- - **`test_timing_fields.py`** - Verify GPS_TIME/RTP_TIMESNAP timing fields
320
- - **`simple_am_radio.py`** - Minimal AM broadcast listener
321
- - **`superdarn_recorder.py`** - Ionospheric radar monitoring
322
- - **`codar_oceanography.py`** - Ocean current radar
323
- - **`hf_band_scanner.py`** - Dynamic frequency scanner
324
- - **`wspr_monitor.py`** - Weak signal propagation reporter
310
+ See [`examples/`](examples/) for runnable scripts:
311
+
312
+ - [`simple_am_radio.py`](examples/simple_am_radio.py) minimal AM listener
313
+ - [`discover_example.py`](examples/discover_example.py) channel discovery on the LAN
314
+ - [`stream_example.py`](examples/stream_example.py) `RadiodStream` sample callback
315
+ - [`rtp_recorder_example.py`](examples/rtp_recorder_example.py) precise-timing RTP recorder
316
+ - [`multi_stream_smoke.py`](examples/multi_stream_smoke.py) `MultiStream` multi-SSRC receiver
317
+ - [`hf_band_scanner.py`](examples/hf_band_scanner.py) dynamic band scanner
318
+ - [`channel_cleanup_example.py`](examples/channel_cleanup_example.py) teardown via frequency=0
319
+ - [`tune.py`](examples/tune.py) interactive tuning utility
320
+ - [`superdarn_recorder.py`](examples/superdarn_recorder.py), [`codar_oceanography.py`](examples/codar_oceanography.py), [`grape_integration_example.py`](examples/grape_integration_example.py) domain-specific recorders
325
321
 
326
322
  ## Use Cases
327
323
 
328
- ### AM/FM/SSB Radio
329
- - Broadcast monitoring
330
- - Ham radio operation
331
- - Shortwave listening
332
-
333
- ### Scientific Research
334
- - WSPR propagation studies
335
- - SuperDARN ionospheric radar
336
- - CODAR ocean current mapping
337
- - Meteor scatter
338
- - EME (moonbounce)
339
-
340
- ### Digital Modes
341
- - FT8/FT4 monitoring
342
- - RTTY/PSK decoding
343
- - DRM digital radio
344
- - HF fax reception
345
-
346
- ### Satellite Operations
347
- - Downlink reception
348
- - Doppler tracking
349
- - Multi-frequency monitoring
350
-
351
- ### Custom Applications
352
- **No assumptions!** Use for anything SDR-related.
324
+ See [docs/RECIPES.md](docs/RECIPES.md) for worked examples of:
325
+
326
+ - **LAN probing** — enumerate radiod instances and their active channels
327
+ - **Fixed-channel pipelines** — WSPR, PSK/FT8, HF timing (bundled band plans, `MultiStream`); see companion projects `wspr-recorder`, `psk-recorder`, `hf-timestd`
328
+ - **Nimble channel switching** — single-channel SWL-style retuning driven from the CLI or an app
329
+ - **SDR portability** — ka9q-python talks to `radiod`, which talks to the SDR; reporting frontend capabilities via `FrontendStatus`. Primary tested frontend is the RX888; AirspyR2 and Airspy HF+ support is in development.
353
330
 
354
331
  ## License
355
332
 
@@ -23,15 +23,15 @@ Control radiod channels for any application: AM/FM/SSB radio, WSPR monitoring, S
23
23
 
24
24
  ## Features
25
25
 
26
- **Zero assumptions** - Works for any SDR application
27
- **Complete API** - All 85+ radiod parameters exposed
28
- **Channel control** - Create, configure, discover channels
29
- **RTP recording** - Generic recorder with timing support and state machine
30
- **Precise timing** - GPS_TIME/RTP_TIMESNAP for accurate timestamps
31
- **Multi-homed support** - Works on systems with multiple network interfaces
32
- **Pure Python** - No compiled dependencies
33
- **Well tested** - Comprehensive test coverage
34
- **Documented** - Comprehensive examples and API reference included
26
+ - **Complete radiod API** all 110+ TLV status/command parameters exposed, generated from ka9q-radio's C headers
27
+ - **Four stream abstractions** `RTPRecorder` (raw packets), `RadiodStream` (samples + gap handling), `ManagedStream` (self-healing single channel), `MultiStream` (shared socket, many SSRCs)
28
+ - **Typed status decoder** `ChannelStatus`, `FrontendStatus`, `PllStatus`, etc. with dotted-path field access
29
+ - **Precise RTP timing** GPS_TIME / RTP_TIMESNAP for sample-accurate wallclock timestamps
30
+ - **LAN discovery** enumerate radiod instances and their active channels via mDNS
31
+ - **CLI + TUI** `ka9q list / query / set / tui` for interactive and scripted control
32
+ - **Multi-homed** explicit interface selection for hosts with multiple NICs
33
+ - **Protocol drift detection** — pinned to a specific ka9q-radio commit, with a sync script
34
+ - **Pure Python** NumPy is the only runtime dependency
35
35
 
36
36
  ## Installation
37
37
 
@@ -178,6 +178,7 @@ monitor.monitor_channel(
178
178
  preset="usb",
179
179
  sample_rate=12000
180
180
  )
181
+ ```
181
182
 
182
183
  ### Channel Cleanup (frequency = 0)
183
184
 
@@ -256,63 +257,39 @@ It auto-skips if `../ka9q-radio` is not present, so CI environments without the
256
257
 
257
258
  ## Documentation
258
259
 
259
- For detailed information, please refer to the documentation in the `docs/` directory:
260
-
261
- - **[API Reference](docs/API_REFERENCE.md)**: Full details on all classes, methods, and functions.
262
- - **[TUI Guide](docs/TUI_GUIDE.md)**: Launching and using the `ka9q tui` Textual terminal UI.
263
- - **[RTP Timing Support](docs/RTP_TIMING_SUPPORT.md)**: Guide to RTP timing and synchronization.
264
- - **[Architecture](docs/ARCHITECTURE.md)**: Overview of the library's design and structure.
265
- - **[Installation Guide](docs/INSTALLATION.md)**: Detailed installation instructions.
266
- - **[Testing Guide](docs/TESTING_GUIDE.md)**: Information on how to run the test suite.
267
- - **[Security Considerations](docs/SECURITY.md)**: Important security information regarding the ka9q-radio protocol.
268
- - **[Changelog](docs/CHANGELOG.md)**: A log of all changes for each version.
269
- - **[Release Notes](docs/releases/)**: Release-specific notes and instructions.
260
+ - **[Getting Started](docs/GETTING_STARTED.md)** first-run walkthrough
261
+ - **[Recipes](docs/RECIPES.md)** — task-oriented cookbook: LAN probing, fixed-channel pipelines (WSPR/PSK/FT8/timing), nimble SWL-style retuning, and using ka9q-python across different SDRs
262
+ - **[API Reference](docs/API_REFERENCE.md)** every public class, method, and function
263
+ - **[Architecture](docs/ARCHITECTURE.md)** module layout, threading, protocol
264
+ - **[CLI Guide](docs/CLI_GUIDE.md)** `ka9q list / query / set / tui` command reference
265
+ - **[TUI Guide](docs/TUI_GUIDE.md)** the Textual terminal UI
266
+ - **[MultiStream Guide](docs/MULTI_STREAM.md)** shared-socket multi-channel receiver
267
+ - **[RTP Timing](docs/RTP_TIMING_SUPPORT.md)** GPS_TIME / RTP_TIMESNAP for sample-accurate timestamps
268
+ - **[Installation](docs/INSTALLATION.md)** · **[Testing](docs/TESTING_GUIDE.md)** · **[Security](docs/SECURITY.md)**
269
+ - **[Changelog](CHANGELOG.md)**
270
270
 
271
271
  ## Examples
272
272
 
273
- See the `examples/` directory for complete applications:
274
-
275
- - **High-Level API**: `ensure_channel()` handles the complexity of checking existing channels, creating new ones only when necessary, and verifying configurations.
276
- - **Destination-Aware Channels**: Support for unique per-application multicast destinations and deterministic IP generation.
277
- - **Stream Sharing**: Deterministic SSRC allocation allows multiple independent applications to share `radiod` streams efficiently.
278
- - **`discover_example.py`** - Channel discovery methods (native Python and control utility)
279
- - **`tune.py`** - Interactive channel tuning utility (Python implementation of ka9q-radio's tune)
280
- - **`tune_example.py`** - Programmatic examples of using the tune() method
281
- - **`rtp_recorder_example.py`** - Complete RTP recorder with timing and state machine
282
- - **`test_timing_fields.py`** - Verify GPS_TIME/RTP_TIMESNAP timing fields
283
- - **`simple_am_radio.py`** - Minimal AM broadcast listener
284
- - **`superdarn_recorder.py`** - Ionospheric radar monitoring
285
- - **`codar_oceanography.py`** - Ocean current radar
286
- - **`hf_band_scanner.py`** - Dynamic frequency scanner
287
- - **`wspr_monitor.py`** - Weak signal propagation reporter
273
+ See [`examples/`](examples/) for runnable scripts:
274
+
275
+ - [`simple_am_radio.py`](examples/simple_am_radio.py) minimal AM listener
276
+ - [`discover_example.py`](examples/discover_example.py) channel discovery on the LAN
277
+ - [`stream_example.py`](examples/stream_example.py) `RadiodStream` sample callback
278
+ - [`rtp_recorder_example.py`](examples/rtp_recorder_example.py) precise-timing RTP recorder
279
+ - [`multi_stream_smoke.py`](examples/multi_stream_smoke.py) `MultiStream` multi-SSRC receiver
280
+ - [`hf_band_scanner.py`](examples/hf_band_scanner.py) dynamic band scanner
281
+ - [`channel_cleanup_example.py`](examples/channel_cleanup_example.py) teardown via frequency=0
282
+ - [`tune.py`](examples/tune.py) interactive tuning utility
283
+ - [`superdarn_recorder.py`](examples/superdarn_recorder.py), [`codar_oceanography.py`](examples/codar_oceanography.py), [`grape_integration_example.py`](examples/grape_integration_example.py) domain-specific recorders
288
284
 
289
285
  ## Use Cases
290
286
 
291
- ### AM/FM/SSB Radio
292
- - Broadcast monitoring
293
- - Ham radio operation
294
- - Shortwave listening
295
-
296
- ### Scientific Research
297
- - WSPR propagation studies
298
- - SuperDARN ionospheric radar
299
- - CODAR ocean current mapping
300
- - Meteor scatter
301
- - EME (moonbounce)
302
-
303
- ### Digital Modes
304
- - FT8/FT4 monitoring
305
- - RTTY/PSK decoding
306
- - DRM digital radio
307
- - HF fax reception
308
-
309
- ### Satellite Operations
310
- - Downlink reception
311
- - Doppler tracking
312
- - Multi-frequency monitoring
313
-
314
- ### Custom Applications
315
- **No assumptions!** Use for anything SDR-related.
287
+ See [docs/RECIPES.md](docs/RECIPES.md) for worked examples of:
288
+
289
+ - **LAN probing** — enumerate radiod instances and their active channels
290
+ - **Fixed-channel pipelines** — WSPR, PSK/FT8, HF timing (bundled band plans, `MultiStream`); see companion projects `wspr-recorder`, `psk-recorder`, `hf-timestd`
291
+ - **Nimble channel switching** — single-channel SWL-style retuning driven from the CLI or an app
292
+ - **SDR portability** — ka9q-python talks to `radiod`, which talks to the SDR; reporting frontend capabilities via `FrontendStatus`. Primary tested frontend is the RX888; AirspyR2 and Airspy HF+ support is in development.
316
293
 
317
294
  ## License
318
295