python-aaronia 0.7.2__tar.gz → 0.7.4__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 (118) hide show
  1. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/CHANGELOG.md +89 -4
  2. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/Cargo.lock +2 -2
  3. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/Cargo.toml +1 -1
  4. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/PKG-INFO +1 -1
  5. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/docs/HTTPSPEC.md +231 -8
  6. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/docs/SDKSPEC.md +10 -6
  7. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/packaging/homebrew/soapy-aaronia.rb +1 -1
  8. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/python-aaronia/Cargo.toml +1 -1
  9. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/Registration.cpp +15 -1
  10. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/http_endpoints.rs +15 -1
  11. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/utils.rs +12 -2
  12. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/.cargo/config.toml +0 -0
  13. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/.gitattributes +0 -0
  14. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/.gitignore +0 -0
  15. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/CONTRIBUTING.md +0 -0
  16. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/DESIGN.md +0 -0
  17. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/LICENSE +0 -0
  18. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/PLUGINS.md +0 -0
  19. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/README.md +0 -0
  20. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/benches/decompress_block.rs +0 -0
  21. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/benches/deinterleave_dual_iq.rs +0 -0
  22. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/benches/parse_int16_packet.rs +0 -0
  23. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/benches/rtsa_open_and_read.rs +0 -0
  24. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/deny.toml +0 -0
  25. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/docs/APPS.md +0 -0
  26. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/docs/FILESPEC.md +0 -0
  27. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/docs/QUICKSTART.md +0 -0
  28. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/docs/USAGE.md +0 -0
  29. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/docs/VERIFICATION.md +0 -0
  30. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/examples/channel_hopping.rs +0 -0
  31. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/examples/device_control.rs +0 -0
  32. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/examples/dump_metadata.rs +0 -0
  33. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/examples/http_iq_quickstart.rs +0 -0
  34. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/examples/native_sdk_basic.rs +0 -0
  35. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/examples/native_sdk_transmit.rs +0 -0
  36. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/examples/noaa_scanner.rs +0 -0
  37. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/examples/python_arrow_example.py +0 -0
  38. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/examples/read_rtsa_file.rs +0 -0
  39. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/examples/soapy_python_example.py +0 -0
  40. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/include/aaronia.h +0 -0
  41. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/packaging/homebrew/README.md +0 -0
  42. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/pyproject.toml +0 -0
  43. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/python-aaronia/README.md +0 -0
  44. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/python-aaronia/aaronia.pyi +0 -0
  45. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/python-aaronia/src/lib.rs +0 -0
  46. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/python-aaronia/test_basic.py +0 -0
  47. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/scripts/ci-local.sh +0 -0
  48. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/AaroniaSoapyDevice.cpp +0 -0
  49. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/AaroniaSoapyDevice.hpp +0 -0
  50. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/CMakeLists.txt +0 -0
  51. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/README.md +0 -0
  52. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeCache.txt +0 -0
  53. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/4.4.2/CMakeCXXCompiler.cmake +0 -0
  54. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/4.4.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
  55. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/4.4.2/CMakeSystem.cmake +0 -0
  56. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/4.4.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +0 -0
  57. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/4.4.2/CompilerIdCXX/a.out +0 -0
  58. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/4.4.2/CompilerIdCXX/apple-sdk.cpp +0 -0
  59. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/CMakeConfigureLog.yaml +0 -0
  60. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/CMakeDirectoryInformation.cmake +0 -0
  61. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/CMakeRuleHashes.txt +0 -0
  62. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/InstallScripts.json +0 -0
  63. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/Makefile.cmake +0 -0
  64. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/Makefile2 +0 -0
  65. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/TargetDirectories.txt +0 -0
  66. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/aaroniaSupport.dir/DependInfo.cmake +0 -0
  67. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/aaroniaSupport.dir/build.make +0 -0
  68. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/aaroniaSupport.dir/cmake_clean.cmake +0 -0
  69. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/aaroniaSupport.dir/compiler_depend.make +0 -0
  70. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/aaroniaSupport.dir/compiler_depend.ts +0 -0
  71. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/aaroniaSupport.dir/depend.make +0 -0
  72. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/aaroniaSupport.dir/flags.make +0 -0
  73. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/aaroniaSupport.dir/link.txt +0 -0
  74. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/aaroniaSupport.dir/progress.make +0 -0
  75. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/cmake.check_cache +0 -0
  76. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/progress.marks +0 -0
  77. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/sdr_aaronia_rs_static.dir/DependInfo.cmake +0 -0
  78. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/sdr_aaronia_rs_static.dir/build.make +0 -0
  79. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/sdr_aaronia_rs_static.dir/cmake_clean.cmake +0 -0
  80. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/sdr_aaronia_rs_static.dir/compiler_depend.make +0 -0
  81. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/sdr_aaronia_rs_static.dir/compiler_depend.ts +0 -0
  82. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/CMakeFiles/sdr_aaronia_rs_static.dir/progress.make +0 -0
  83. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/Makefile +0 -0
  84. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/build-test/cmake_install.cmake +0 -0
  85. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/packaging/install.ps1 +0 -0
  86. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/packaging/install.sh +0 -0
  87. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/soapy-aaronia/print.cmake +0 -0
  88. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/c_api.rs +0 -0
  89. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/decompression.rs +0 -0
  90. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/detection.rs +0 -0
  91. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/error.rs +0 -0
  92. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/file_source.rs +0 -0
  93. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/http_sink.rs +0 -0
  94. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/http_source.rs +0 -0
  95. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/http_streaming.rs +0 -0
  96. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/lib.rs +0 -0
  97. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/native_sdk.rs +0 -0
  98. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/sdk_sink.rs +0 -0
  99. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/sdk_source.rs +0 -0
  100. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/sdr_source_impl.rs +0 -0
  101. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/seify_impl.rs +0 -0
  102. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/unified_sink.rs +0 -0
  103. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/src/unified_source.rs +0 -0
  104. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/test.cmake +0 -0
  105. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/c_api_test.rs +0 -0
  106. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/http_mock_test.rs +0 -0
  107. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/http_resilience_test.rs +0 -0
  108. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/http_sink_test.rs +0 -0
  109. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/integration_test.rs +0 -0
  110. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/live_smoke.rs +0 -0
  111. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/native_sdk_load.rs +0 -0
  112. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/properties.proptest-regressions +0 -0
  113. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/properties.rs +0 -0
  114. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/rtsa_negative_test.rs +0 -0
  115. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/sdr_source_impl_test.rs +0 -0
  116. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/spec_coverage.rs +0 -0
  117. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/test_cw_mag.rs +0 -0
  118. {python_aaronia-0.7.2 → python_aaronia-0.7.4}/tests/test_cw_meta.rs +0 -0
@@ -4,6 +4,90 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [v0.7.4] - 2026-08-12
8
+
9
+ ### Fixed
10
+ - **The SoapySDR plugin ignored an unrecognised `format=` silently.**
11
+ A device string carrying `format=int16` — the wire name rather than
12
+ the plugin's `I16` — streamed the default format while claiming
13
+ otherwise. It now warns and continues. The server behaves the same
14
+ way and worse: an unrecognised `format=` on `/stream` serves the
15
+ RTSA file format with HTTP 200 rather than an error, so a typo
16
+ changes the wire format entirely. `raw16`, which Aaronia's own Qt
17
+ reference client sends, is a working alias for `int16`.
18
+
19
+ ### Documentation
20
+ - Checked Aaronia's V6 remote control notes (rev 4, May 2026) against
21
+ the hardware. `/remoteconfig` enum fields take an index as well as a
22
+ label; one `simpleconfig` PUT can carry several groups, and groups
23
+ other than `main` work; and a PUT naming a block that is not in the
24
+ mission returns 200 and changes nothing, which
25
+ `simple_remote_config` now warns about since it reports `Ok(())` for
26
+ a write that did not happen. In the config-tree form the receiver
27
+ name is ignored altogether — the write is routed by `config.name`.
28
+ - Documented loading a mission over `/control`, and that every
29
+ `/control` payload needs its `type` or the server answers `400`.
30
+ Loading a mission is deliberately not exposed by the crate: swapping
31
+ the mission under a running capture should be a caller's decision,
32
+ not a side effect.
33
+ - Noted that RTSA-Suite has no status endpoint. Aaronia's own liveness
34
+ check reads the `404` from `/api/status` as proof the server is up.
35
+ - **What "Full" means on a full V6 is unresolved.** A V6 ECO follows the
36
+ SDK's `spanfreq <= receiverclock / 1.5`, measured. Aaronia's Remote
37
+ Config screenshots show a full V6 at a 92 MHz clock delivering
38
+ 92.16 MHz of IQ samples per second at span "Full" — the clock itself.
39
+ `iq_sample_rates_for_clock` may therefore understate the top of the
40
+ ladder by 1.5x for a full V6 at a non-default clock; it says so now.
41
+ Settling it needs a full V6.
42
+ - HTTPSPEC contradicted itself on the Remote Config licence, asserting
43
+ in one section that writes need it and in another that a live
44
+ unlicensed system accepts them. The second is what the hardware does,
45
+ re-confirmed for centre frequency, decimation, reference level and
46
+ the preamplifier.
47
+ - SDKSPEC still gave the V6 ECO's receiver clock as 61.44 MHz, which
48
+ 0.6.2 corrected in code to 92.16 MHz. 61.44 MHz is the ECO's top IQ
49
+ rate, that clock over 1.5; the document had the two confused.
50
+ - **A marker stream is not a categories packet**, which the previous
51
+ draft of this entry got wrong. Aaronia's example declares
52
+ `payload: "spectra"`, and spectra samples are a 2D array, so its
53
+ nesting is correct for what it says it is. Its three frequency fields
54
+ are all zero, so the category names and ranges are the only
55
+ description of what the numbers mean.
56
+ - Aaronia's endpoint specification (rev 11) settles several things this
57
+ document had only inferred, and their support answers go further.
58
+ `/control` takes PUT only, and a command reaches every block that
59
+ understands it unless `receiverUUID` or `receiverName` scopes it —
60
+ the specification says such commands cannot be addressed to a block,
61
+ which their support corrected in 2024. The per-type settings are now
62
+ listed in full, including `deviceconnect` and `camera`, which this
63
+ crate does not model. Zones cannot be configured remotely at all.
64
+ The server starts dropping data once its outbound TCP buffer passes
65
+ 8 MB, which is the mechanism behind most unexplained gaps.
66
+ `/healthstatus` is organised as `info`, `status`, `health`,
67
+ `settings` and `components`, the last being how satellites attached
68
+ over HTTP appear in a local tree.
69
+ - **`status/iqsamples` is the native rate, not the delivered one.** It
70
+ held at 61.44 MHz while the same device delivered 15.36, then 7.68,
71
+ then 61.44 MS/s. It looks like a sample rate and is not the one your
72
+ stream is running at; read `sampleFrequency` from packet metadata.
73
+ Documented the other fields a V6 ECO reports alongside it.
74
+ - **One HTTP Server and one HTTP Client connection are free**;
75
+ additional instances and connections are licensed separately, as are
76
+ Stream Merger and Stream Splitter. Running this crate and a second
77
+ client against one server at the same time is a second connection —
78
+ the licence limit most likely to be met in practice, and unrelated to
79
+ Remote Config.
80
+
81
+ ## [v0.7.3] - 2026-08-12
82
+
83
+ ### Fixed
84
+ - The Windows leg of the new module load check could not run: vcpkg's
85
+ SoapySDR port ships no `SoapySDRUtil`, so the check failed rather
86
+ than verifying anything, and 0.7.2 published no release archives.
87
+ Where the tool is absent the packaged DLL is now loaded directly,
88
+ which still catches a module whose dependencies do not resolve away
89
+ from the build machine.
90
+
7
91
  ## [v0.7.2] - 2026-08-12
8
92
 
9
93
  ### Fixed
@@ -31,10 +115,11 @@ All notable changes to this project will be documented in this file.
31
115
 
32
116
  ## [v0.7.1] - 2026-08-12
33
117
 
34
- An incomplete fix for the macOS module, superseded by 0.7.2. It reached
35
- crates.io and PyPI but published no GitHub release: the new load check
36
- refused to ship a macOS module that would not open. The Rust crate and
37
- the Python wheels are sound and identical in content to 0.7.2.
118
+ An incomplete fix for the macOS module, superseded by 0.7.2. Like
119
+ 0.7.2, it reached crates.io and PyPI but published no release archives,
120
+ because the new load check refused to ship a macOS module that would
121
+ not open. Its crate and wheels are sound and identical in content to
122
+ 0.7.3.
38
123
 
39
124
  ## [v0.7.0] - 2026-08-12
40
125
 
@@ -3027,7 +3027,7 @@ dependencies = [
3027
3027
 
3028
3028
  [[package]]
3029
3029
  name = "python-aaronia"
3030
- version = "0.7.2"
3030
+ version = "0.7.4"
3031
3031
  dependencies = [
3032
3032
  "arrow",
3033
3033
  "num-complex",
@@ -3556,7 +3556,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
3556
3556
 
3557
3557
  [[package]]
3558
3558
  name = "sdr-aaronia-rs"
3559
- version = "0.7.2"
3559
+ version = "0.7.4"
3560
3560
  dependencies = [
3561
3561
  "anyhow",
3562
3562
  "bitflags 2.13.1",
@@ -2,7 +2,7 @@
2
2
  name = "sdr-aaronia-rs"
3
3
  description = "Unified Rust interface for Aaronia Spectran Spectrum Analyzers / SDRs, featuring Python bindings, a SoapySDR plugin, HTTP streaming, and native SDK support."
4
4
  license = "GPL-3.0-or-later"
5
- version = "0.7.2"
5
+ version = "0.7.4"
6
6
  edition = "2024"
7
7
  repository = "https://github.com/isaacbentley/sdr-aaronia-rs"
8
8
  readme = "README.md"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aaronia
3
- Version: 0.7.2
3
+ Version: 0.7.4
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
@@ -161,6 +161,43 @@ http://localhost:54664/stream?format=int16&scale=1000000
161
161
  http://localhost:54664/stream?rate_reduction=10
162
162
  ```
163
163
 
164
+ ### An unknown `format` is not an error
165
+
166
+ `format=` accepts `json`, `int16`, `float16` and `float32`. `raw16` is
167
+ an accepted alias for `int16` — Aaronia's own Qt reference client
168
+ defaults to it — and produces byte-identical framing.
169
+
170
+ Anything the server does not recognise serves **the RTSA file format**
171
+ instead: a `DSFH` header followed by `STRM`/`ANTA` chunks, with HTTP
172
+ 200 and no warning. A typo in `format=` therefore yields a completely
173
+ different wire format rather than an error, and a parser expecting
174
+ JSON-plus-binary will fail somewhere well past the point that would
175
+ have identified the cause. Verified against a live server: `format=`
176
+ with a nonsense value returned `DSFH`.
177
+
178
+ This crate builds the string from an enum, so it cannot typo, and the
179
+ SoapySDR plugin now warns on an unrecognised `format=` device argument
180
+ rather than silently falling back to the default.
181
+
182
+ ### When the server drops data
183
+
184
+ The HTTP server block starts dropping data once its outbound TCP
185
+ buffer passes **8 MB**. Nothing announces it; the loss shows up as a
186
+ gap between the timestamps of two adjacent packets, which is what
187
+ `DropDetector` watches for. A slow consumer, a slow link, or a rate
188
+ the network cannot carry all end here, so reducing the wire format
189
+ (`format=int16`) or the rate (`rate_reduction=n`) is the fix rather
190
+ than a larger client-side buffer.
191
+
192
+ ### Liveness
193
+
194
+ There is no status endpoint. Aaronia's own remote control notes probe
195
+ with `curl -v http://127.0.0.1:54664/api/status` and treat the `404 Not
196
+ Found` as the answer: a reply of any kind proves the port is open, the
197
+ mission is loaded and the HTTP Server block is running. A connection
198
+ refused or a timeout means it is not. `/info` serves the same purpose
199
+ and returns something useful, which is what this crate uses.
200
+
164
201
  ### Application Process Control
165
202
  **URL**: `/app/process`
166
203
  **Method**: PUT
@@ -250,6 +287,42 @@ packet-metadata object, so `payload`, `minPower`, `maxPower`, and
250
287
  `stepFrequency` (the sample rate) is optional; `push: true` marks the packet for immediate transmission.
251
288
 
252
289
  ### Control Endpoint
290
+
291
+ `/control` accepts **PUT only**. A GET — which is what a browser does
292
+ with the URL — is not supported.
293
+
294
+ **A command reaches every block that understands it, unless you scope
295
+ it.** Aaronia's 2022 specification says control commands "are not
296
+ addressed to a specific RTSA block and will be processed from all RTSA
297
+ blocks in the block graph", which is true as a default. Their support
298
+ staff refined it in 2024: `receiverUUID` and `receiverName` "can be
299
+ used to limit the requested setting to individual blocks", and "in some
300
+ cases it may be necessary to specify them". Read the names or UUIDs
301
+ from `/remoteconfig` first if you need to target one block.
302
+
303
+ These are one-off requests. Aaronia's own words: if they cannot be
304
+ executed, or conflict with the local configuration, the behaviour is
305
+ undefined — nothing reports the conflict.
306
+
307
+ **The settings each `type` accepts**, per Aaronia support (January
308
+ 2024), which goes well beyond the published specification:
309
+
310
+ | `type` | Settings |
311
+ | :--- | :--- |
312
+ | `capture` | `receiverUUID`, `receiverName`, `frequencyCenter`, `frequencyStart`, `frequencyBins`, `referenceLevel`, `start` — plus `frequencySpan` and `frequencyEnd`, which the specification documents and this crate uses |
313
+ | `deviceconnect` | `receiverUUID`, `receiverName`, `start` — connect or disconnect a device |
314
+ | `streaming` | `receiverUUID`, `receiverName`, `filename`, `start` |
315
+ | `recording` | `receiverUUID`, `receiverName`, `filename`, `start` |
316
+ | `mission` | `save`, `reload`, `load` (with the path in `file`) |
317
+ | `antenna` | `receiverUUID`, `receiverName`, `latitude`+`longitude` (both or neither), `azimuth`+`declination`, `rotate` |
318
+ | `camera` | `receiverUUID`, `receiverName`, `latitude`+`longitude`, `azimuth`+`declination`, `aperture`, `channel`, `altitude`, `start` |
319
+
320
+ `start`, `rotate`, `save`, `load` and `reload` are booleans. A
321
+ `filename` must be an absolute path **on the machine running
322
+ RTSA-Suite**, with forward slashes.
323
+
324
+ Zones cannot be configured this way; Aaronia state that remote
325
+ configuration of zones is not supported.
253
326
  **URL**: `/control`
254
327
  **Method**: PUT
255
328
  **Description**: Send commands to the RTSA suite
@@ -320,7 +393,7 @@ packet-metadata object, so `payload`, `minPower`, `maxPower`, and
320
393
  }
321
394
  ```
322
395
 
323
- #### Save/Reload Mission
396
+ #### Save/Reload/Load Mission
324
397
  ```json
325
398
  {
326
399
  "save": true,
@@ -328,6 +401,28 @@ packet-metadata object, so `payload`, `minPower`, `maxPower`, and
328
401
  }
329
402
  ```
330
403
 
404
+ A mission can also be swapped outright, which is how a headless station
405
+ changes what it is running. `load` takes an absolute path to an `.rmix`
406
+ on the machine running RTSA-Suite, not on the client:
407
+ ```json
408
+ {
409
+ "type": "mission",
410
+ "load": true,
411
+ "file": "C:/Aaronia/Recordings/HTTP streaming/http_test.rmix"
412
+ }
413
+ ```
414
+ A mission carrying an HTTP Server block must already be running, or
415
+ there is nothing listening to accept the request. Aaronia's remote
416
+ control notes (rev 4, May 2026) give this as a `curl` invocation from
417
+ an elevated prompt. This crate does not expose it: swapping the mission
418
+ out from under a running capture is the caller's decision to make
419
+ deliberately, not a side effect of a library call.
420
+
421
+ **Every `/control` payload needs its `type`.** A body without one is
422
+ rejected with `400` and the text `Type argument missing`, so a
423
+ hand-built payload that omits it fails loudly rather than silently —
424
+ unlike a partial capture request, which is accepted and ignored.
425
+
331
426
  ### Configuration Endpoints
332
427
 
333
428
  #### Server Info (`/info`)
@@ -430,8 +525,18 @@ Notes verified against a live V6 ECO:
430
525
  and `frequencySpan` are both present.
431
526
  - **The `receiverName` key is case-tolerant.** `receivername` was accepted
432
527
  identically.
433
- - Enum-valued settings are written as their label string, for example
434
- `decimation` as `"1 / 128"`, not as an index.
528
+ - **Enum-valued settings take either the label string or the index.**
529
+ Aaronia's example writes `decimation` as `"1 / 128"`; writing
530
+ `decimation0` as the integer `3` was accepted and applied identically
531
+ (verified against `/sample`: index 3 gave 7.68 MHz, index 2 gave
532
+ 15.36 MHz). Indices are positions in the `values` list that
533
+ `GET /remoteconfig` reports for that item.
534
+ - **Groups other than `main` work**, and several can go in one PUT:
535
+ `{"main": {...}, "calibration": {"preamp": 1}}` applied both.
536
+ - **An unknown block name is a silent no-op.** A `simpleconfig` PUT
537
+ naming a block that is not in the mission returns HTTP 200 and changes
538
+ nothing. There is no error to catch, so read the value back if it
539
+ matters.
435
540
  - Other keys the example writes: `run` (bool), `preamp` (`"Auto"`),
436
541
  `reflevel` (float), and `filerecord` (bool) plus a filename template on
437
542
  a FileWriter block, which is how it starts and stops recording.
@@ -445,7 +550,15 @@ Notes verified against a live V6 ECO:
445
550
  }
446
551
  }
447
552
  ```
448
- `receiverName` must match a block in the running mission; `HttpEndpointsClient::find_iq_demodulator_block_name` auto-discovers it.
553
+ `receiverName` must match a block in the running mission;
554
+ `HttpEndpointsClient::find_iq_demodulator_block_name` auto-discovers it.
555
+ A name that matches nothing still returns 200 (see above).
556
+
557
+ In the full `{request, config}` form the receiver name is ignored
558
+ altogether: the write is routed by `config.name`. Sending
559
+ `receivername`, `receiverName` or no name at all applied the same
560
+ change. Nothing depends on getting that key right, and nothing warns
561
+ when it is wrong.
449
562
 
450
563
  **Configuration Item Fields**:
451
564
  | Field | Description |
@@ -469,6 +582,28 @@ configuration tree (`HealthStatus` is an alias for `ConfigItem`) rather
469
582
  than the typed shape below, which describes the upstream block-health
470
583
  fields.
471
584
 
585
+ **Subgroups** per health-aware block, per Aaronia's specification:
586
+ `info`, `status`, `health`, `settings`, and `components` — the last a
587
+ recursive list of sub-blocks when satellites are attached over HTTP,
588
+ which is how a remote station's devices show up in a local tree.
589
+
590
+ **What a V6 ECO actually reports** under `status` and `health`,
591
+ alongside the `info` fields below:
592
+
593
+ | Item | Example | Meaning |
594
+ | :--- | :--- | :--- |
595
+ | `status/iqsamples` | 61439323 | **Native** IQ rate in Hz, not the delivered one. Measured constant at 61.44 MHz while the same device delivered 15.36, then 7.68, then 61.44 MS/s — it does not follow the decimation setting |
596
+ | `status/usbbuffer` | 0.0625 | USB buffer fill, fraction |
597
+ | `status/adcrange` | 17.16 | ADC headroom in dB |
598
+ | `status/strmtimedist` | 5.96e-06 | Stream time distance in seconds |
599
+ | `health/fronttemp` | 64.7 | Frontend temperature, °C |
600
+ | `health/fpgatemp` | 52.5 | FPGA temperature, °C |
601
+ | `health/boardpower` | 8.975 | Board power draw, W |
602
+
603
+ `iqsamples` is the one to be careful with: it looks like a sample rate
604
+ and is not the one your stream is running at. Read `sampleFrequency`
605
+ from packet metadata for that.
606
+
472
607
  **Health Status Fields**:
473
608
  | Field | Description |
474
609
  | :--- | :--- |
@@ -577,7 +712,35 @@ The samples in a category ordered packet have one measurement per category.
577
712
  }
578
713
  ```
579
714
 
580
- As with histograms, category samples are a flat number array (one value per category).
715
+ As with histograms, category samples are a flat number array (one value
716
+ per category) — that is what a live server produced.
717
+
718
+ **A marker stream is not a categories packet.** Aaronia's remote
719
+ control notes show the Spectrum block's `Marker` output wired to an
720
+ HTTP Server, and the result looks like this:
721
+
722
+ ```json
723
+ {
724
+ "payload": "spectra",
725
+ "startFrequency": 0, "endFrequency": 0, "sampleFrequency": 0,
726
+ "sampleSize": 4, "sampleDepth": 1,
727
+ "categories": [
728
+ { "name": "Slow Sine(R)", "startFrequency": 2403000000, "endFrequency": 2405000000 },
729
+ { "name": "Marker", "startFrequency": 2412852325.3, "endFrequency": 2412852335.3 }
730
+ ],
731
+ "samples": [[-78.6, -57.26, -47.28, -114.25]]
732
+ }
733
+ ```
734
+
735
+ It carries a `categories` array but declares `payload: "spectra"`, and
736
+ spectra samples are a 2D array — one row per frame — so the nesting is
737
+ correct for what it says it is, not a contradiction of the flat
738
+ categories form above. `sampleSize` is the number of values in a row,
739
+ here one per category.
740
+
741
+ What is worth knowing before parsing one: all three frequency fields
742
+ are `0`, so nothing can be derived from them, and the category names
743
+ and ranges are the only description of what the numbers mean.
581
744
 
582
745
  ### Antenna Data
583
746
  Data captured using antennas with location or directional information.
@@ -614,7 +777,44 @@ and `Location and Time`; `sclksource` offers `Consumer`, `Oscillator`,
614
777
 
615
778
  `decimation0` takes the same labels as the SDK's `main/decimation`,
616
779
  `"Full"` through `"1 / 512"`, verified by writing one over HTTP. Both
617
- transports drive the same divider.
780
+ transports drive the same divider. Over HTTP the index works as well as
781
+ the label: writing `3` and reading `/sample` back gave 7.68 MHz, and `2`
782
+ gave 15.36 MHz, which is 61.44 MHz halved that many times on a V6 ECO.
783
+
784
+ #### Unresolved: the full V6's top rate
785
+
786
+ The SDK constrains `spanfreq * 1.5 <= receiverclock`, and a V6 ECO
787
+ follows it: its top IQ rate measures 61.44 MHz against the 92.16 MHz
788
+ clock the crate assumes for it. `iq_sample_rates_for_clock` takes that
789
+ ratio as the rule, so it puts a full V6 on the `245MHz` clock at
790
+ 163.84 MHz.
791
+
792
+ Aaronia's own figures do not agree. Their endpoint specification closes
793
+ with a note about achieving "the full 250M samples of IQ data", their
794
+ block documentation advertises "a real-time bandwidth of up to 245MHz
795
+ each" for the V6's two inputs, and both round to the 245.76 MHz that
796
+ the `245MHz` clock label denotes — the clock itself, not two thirds of
797
+ it.
798
+
799
+ There is a reading that reconciles them. The clock list runs past
800
+ `245MHz` to `492MHz` (491.52 MHz), and 245.76 MHz of span satisfies the
801
+ 1.5 rule against that clock with room to spare. On that reading 245 MHz
802
+ of real-time bandwidth is real but needs the fastest clock, and the
803
+ `245MHz` label tops out at 163.84 MHz exactly as the crate computes.
804
+
805
+ What does not fit either reading is the Remote Config panel Aaronia
806
+ published in 2021 and again in 2022: a full V6 with the clock set to
807
+ `92MHz` reporting roughly 92.16 MHz of IQ samples per second. That
808
+ counter is not the delivered rate — measured on an ECO, `iqsamples`
809
+ held at 61.44 MHz while the device was actually delivering 15.36 and
810
+ then 7.68 MHz, so it reports the native undecimated rate. Taken at face
811
+ value it says a full V6 at a 92 MHz clock has a native rate of
812
+ 92.16 MHz, which the 1.5 rule forbids.
813
+
814
+ No full V6 has been available to measure, so this stays open. The
815
+ practical guidance is unchanged: the ECO path is verified rung by rung,
816
+ and for anything else read the rate the device reports in its stream
817
+ metadata rather than trusting a computed ladder.
618
818
 
619
819
  ### Two things that do not carry over
620
820
 
@@ -638,6 +838,20 @@ transports drive the same divider.
638
838
  - `/info` - Device information
639
839
  - `/healthstatus` - Device health monitoring
640
840
 
841
+ **HTTP Server and Client blocks are themselves licensed, and the free
842
+ tier is one of each.** Aaronia's staff put it plainly in the HTTP
843
+ Server thread: only one HTTP Server instance is included in the free
844
+ RTSA-Suite PRO licence and additional instances must be licensed
845
+ separately, the same going for the HTTP Client, where only one
846
+ connection is free. Stream Merger and Stream Splitter, the blocks that
847
+ would otherwise let several streams share one connection, are not in
848
+ the free licence either.
849
+
850
+ This is the licence limit most likely to be met in practice: running
851
+ this crate and a second client — a SoapySDR application, say — against
852
+ one server at the same time is a second connection. It has nothing to
853
+ do with the Remote Config licence discussed below.
854
+
641
855
  **Remote Configuration** (`/remoteconfig`):
642
856
  - Device parameter configuration.
643
857
  - Aaronia sells a "Remote Config" license, and this document previously
@@ -655,10 +869,17 @@ transports drive the same divider.
655
869
  and may be what actually matters.
656
870
  - This crate does not depend on the answer: it tunes through `/control`,
657
871
  which needs no license.
872
+ - Re-confirmed 2026-08-12 against RTSA-Suite PRO and a V6 ECO on the
873
+ same unlicensed system, in both payload forms, for `centerfreq0`,
874
+ `decimation0`, `reflevel0` and `calibration/preamp`.
658
875
 
659
876
  **License Detection Methods**:
660
877
 
661
- **Important**: Read access to `/remoteconfig` is available WITHOUT license, but write operations require the license. Because reads are license-free, a read-only check cannot distinguish "licensed" from "unlicensed" — only a write test can.
878
+ **Important**: reads of `/remoteconfig` are license-free, so a read-only
879
+ check cannot prove write capability either way — only a write test can.
880
+ It cannot prove the *license* either: writes succeeded on an unlicensed
881
+ system (see above), so a successful probe means "this server accepts
882
+ writes", not "this server is licensed".
662
883
 
663
884
  The client therefore exposes two methods:
664
885
 
@@ -793,8 +1014,10 @@ fn parse_iq_int16(data: &[u8], metadata_scale: f32) -> Vec<Complex32> {
793
1014
  |---------|------|---------|
794
1015
  | 1.0 | 2025-01-11 | Initial HTTP specification from original documentation |
795
1016
  | 2.0 | 2025-01-11 | Enhanced with comprehensive streaming protocol specification and implementation guidelines |
1017
+ | 2.4 | 2026-08-12 | Added Aaronia support's full `/control` settings list (`deviceconnect`, `camera`, per-type fields, `receiverUUID`/`receiverName` scoping), which supersedes the specification's claim that commands cannot be addressed to a block; documented that an unrecognised `format=` silently serves the RTSA file format and that `raw16` aliases `int16`, both verified live |
1018
+ | 2.3 | 2026-08-12 | Folded in Aaronia's endpoint specification (rev 11) and the block forum threads: `/control` broadcasts to every block and is PUT-only, the server drops data past an 8 MB outbound buffer, `/healthstatus` subgroups and the fields a V6 ECO reports, and the one-server/one-client free-licence limit. Measured that `status/iqsamples` is the native rate, not the delivered one. Corrected the marker-stream entry: it declares `payload: "spectra"`, so its nested samples are the spectra form and not a counter-example to flat categories |
1019
+ | 2.2 | 2026-08-12 | Verified Aaronia's V6 remote control notes (rev 4) against hardware: enum writes by index, multi-group and non-`main` `simpleconfig` PUTs, the silent no-op on an unknown block name, the ignored receiver name in the config-tree form; documented mission loading and the `type` requirement on `/control`, the absence of a status endpoint, and the unresolved conflict over what "Full" means on a full V6; resolved a contradiction over what the Remote Config licence gates |
796
1020
  | 2.1 | 2026-08-06 | Live-hardware corrections folded in (two-byte separator, spectra frame counting, `scale` inversion); documented `/samples`, the `/sample` TX push, and the `simpleconfig` PUT form; corrected `limit` semantics, field types, and flat histogram/categories sample arrays; removed decorative icons |
797
-
798
1021
  ---
799
1022
 
800
1023
  ## Sources and Attribution
@@ -52,9 +52,9 @@ The Aaronia RTSA Vendor SDK provides low-level, high-performance access to Aaron
52
52
  * **SpectranV6 ECO**: `spectranv6eco/raw`, `spectranv6eco/iqreceiver`, `spectranv6eco/iqtransceiver`, `spectranv6eco/iqtransmitter`, `spectranv6eco/sweepsa`
53
53
  * **Configuration Tree**: Hierarchical configuration system with verified parameters:
54
54
  * **Clock Rates** (V6): 46MHz (46.08), 61MHz (61.44), 76MHz (76.80), 92MHz (92.16), 122MHz (122.88), 184MHz (184.32), 245MHz (245.76), 492MHz (491.52) — see the full label table under [Rust Binding Notes](#rust-binding-notes)
55
- * **Clock Rates** (V6 ECO): Fixed at 61.44 MHz
55
+ * **Clock Rates** (V6 ECO): fixed at 92.16 MHz. Its top IQ rate is 61.44 MHz, which is that clock over 1.5 — the two are easy to confuse and this document once recorded the rate as the clock
56
56
  * **Decimation**: Full, 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, 1/128, 1/256, 1/512
57
- * **IQ Mode Sample Rate**: equal to `spanfreq` (constraint: `spanfreq ≤ receiverclock / 1.5`)
57
+ * **IQ Mode Sample Rate**: equal to `spanfreq` (constraint: `spanfreq ≤ receiverclock / 1.5`). Measured on a V6 ECO, untested on a full V6, and not obviously consistent with Aaronia's own 245 MHz / 250 Msample figures for the V6 — see [HTTPSPEC](HTTPSPEC.md#unresolved-the-full-v6s-top-rate)
58
58
  * **Health Monitoring**: Real-time device status including temperatures, sample rates, power levels, USB statistics, GPS data
59
59
 
60
60
  The SDK is designed for building custom spectrum analysis applications, SDR integration, and specialized RF measurement tools.
@@ -256,8 +256,8 @@ source.open_device("spectranv6/raw", &serial_wide)?;
256
256
  `NativeSdkSource::configure_iq_receiver` calls
257
257
  `utils::validate_iq_mode(span, clock)` after applying the config,
258
258
  where `clock` is read live from `device/receiverclock` via
259
- `AARTSAAPI_ConfigGetString` (or 61.44 MHz on eco devices, which expose no
260
- such key and run at a fixed clock). The check enforces
259
+ `AARTSAAPI_ConfigGetString` (or `DEFAULT_RECEIVER_CLOCK_HZ`, 92.16 MHz,
260
+ on eco devices, which expose no such key and run at a fixed clock). The check enforces
261
261
  `span * 1.5 <= clock` and returns a typed error before the device starts.
262
262
 
263
263
  The ConfigItem labels the SDK exposes are *rounded* — `"92MHz"` is
@@ -911,8 +911,12 @@ reads a single stream and deinterleaves it, so it writes `Rx12`.
911
911
  | Raw-mode open string | `spectranv6/raw` | `spectranv6eco/rtsa` |
912
912
 
913
913
  The clock matters beyond configuration: with `span * 1.5 <=
914
- receiverclock`, a V6 on the fast clock reaches roughly 163 MHz of span
915
- where the ECO's fixed clock allows 61.44 MHz.
914
+ receiverclock`, a V6 on the `245MHz` clock reaches roughly 163 MHz of
915
+ span where the ECO's fixed clock allows 61.44 MHz. Aaronia advertise
916
+ 245 MHz of real-time bandwidth per input, which under this rule would
917
+ need the `492MHz` clock; see
918
+ [HTTPSPEC](HTTPSPEC.md#unresolved-the-full-v6s-top-rate) for why that
919
+ is not settled.
916
920
 
917
921
  ### Sample rates
918
922
 
@@ -12,7 +12,7 @@
12
12
  class SoapyAaronia < Formula
13
13
  desc "SoapySDR plugin for Aaronia SPECTRAN V6 spectrum analyzers"
14
14
  homepage "https://github.com/isaacbentley/sdr-aaronia-rs"
15
- version "0.7.2"
15
+ version "0.7.4"
16
16
  license "GPL-3.0-or-later"
17
17
 
18
18
  # Prebuilt modules: the plugin statically links its Rust core, so there
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "python-aaronia"
3
- version = "0.7.2"
3
+ version = "0.7.4"
4
4
  edition = "2024"
5
5
  description = "Python bindings for sdr-aaronia-rs (Aaronia SPECTRAN V6 SDR source)"
6
6
  license = "GPL-3.0-or-later"
@@ -111,8 +111,22 @@ static SoapySDR::Device *makeAaronia(const SoapySDR::Kwargs &args) {
111
111
  }
112
112
  // format=I16 enables the genuine low-bandwidth HTTP wire mode
113
113
  // (int16 from the server), optionally with scale=N.
114
+ //
115
+ // Checked here rather than left to the C API, which ignores a value
116
+ // it does not recognise and returns nothing to say so. A typo would
117
+ // otherwise stream the default format while the device string
118
+ // claims something else — and the server is no help either: it
119
+ // answers an unknown `format=` with the RTSA file format rather
120
+ // than an error.
114
121
  if (args.count("format") != 0) {
115
- aaronia_source_builder_stream_format(builder, args.at("format").c_str());
122
+ const std::string &fmt = args.at("format");
123
+ if (fmt != "F32" && fmt != "F16" && fmt != "I16") {
124
+ SoapySDR::logf(SOAPY_SDR_WARNING,
125
+ "aaronia: ignoring format=%s; expected F32, F16 or I16",
126
+ fmt.c_str());
127
+ } else {
128
+ aaronia_source_builder_stream_format(builder, fmt.c_str());
129
+ }
116
130
  }
117
131
  if (args.count("scale") != 0) {
118
132
  aaronia_source_builder_stream_scale(builder, parseArgDouble(args, "scale"));
@@ -838,7 +838,21 @@ impl HttpEndpointsClient {
838
838
  /// `main` is the typical group, but any subset of the block's
839
839
  /// configuration tree may be passed via `config_groups`. Keys are
840
840
  /// group names ("main", "device", "calibration"); values are field
841
- /// → `serde_json::Value` maps.
841
+ /// → `serde_json::Value` maps. Several groups in one call are
842
+ /// applied together.
843
+ ///
844
+ /// Enum fields take either the label the device reports or its
845
+ /// index in that item's `values` list.
846
+ ///
847
+ /// **A wrong `receiver_name` is silently accepted.** Naming a block
848
+ /// that is not in the running mission returns HTTP 200 and changes
849
+ /// nothing, so this returns `Ok(())` for a write that did not
850
+ /// happen. The server offers nothing to check against, so resolve
851
+ /// the name once from [`Self::get_config`] (or
852
+ /// [`Self::find_iq_demodulator_block_name`]) when the session
853
+ /// starts, rather than hard-coding a block name and trusting the
854
+ /// status code. Read the value back afterwards when a write has to
855
+ /// be certain.
842
856
  pub async fn simple_remote_config(
843
857
  &self,
844
858
  receiver_name: &str,
@@ -333,8 +333,18 @@ pub fn iq_sample_rates() -> [f64; 10] {
333
333
  /// [`DEFAULT_RECEIVER_CLOCK_HZ`], verified rung by rung. A full V6 can
334
334
  /// select other clocks — Aaronia's own samples use `"92MHz"` and
335
335
  /// `"245MHz"` — and the rates there follow the same constraint but have
336
- /// not been confirmed against hardware. Read `device/receiverclock`
337
- /// from the device and pass it here rather than assuming.
336
+ /// not been confirmed against hardware.
337
+ ///
338
+ /// **The 1.5 may be wrong for a full V6.** Aaronia advertise 245 MHz of
339
+ /// real-time bandwidth per input and "the full 250M samples of IQ
340
+ /// data", which is the `245MHz` clock label itself rather than the
341
+ /// 163.84 MHz this returns for it. That may simply mean the fastest
342
+ /// rate needs the `492MHz` clock, where 245.76 MHz of span does
343
+ /// satisfy the 1.5 rule; a published Remote Config panel showing a
344
+ /// full V6 at a `92MHz` clock with a 92.16 MHz native rate fits
345
+ /// neither reading. Until one can be measured, treat this as the ECO's
346
+ /// ladder and prefer the rate a device reports in its stream metadata
347
+ /// over the one computed here.
338
348
  pub fn iq_sample_rates_for_clock(receiver_clock_hz: f64) -> [f64; 10] {
339
349
  let top = receiver_clock_hz / 1.5;
340
350
  let mut rates = [0.0; 10];
File without changes
File without changes
File without changes
File without changes