Add full FM band scan for building a station/channel list

New TunerService::scanFullFmBand(): tunes to the band bottom then seeks up
repeatedly (reusing the existing hardware-seek + RDS-name-poll machinery
from scanForStation()) until the sweep wraps back around, collecting every
station that clears the existing scan RSSI/SNR thresholds. Returns the
list without touching saved presets or leaving the tuner in any particular
place — callers decide what to do with the results.

New POST /api/tuner/scan/full endpoint (core::TunerFmScannedStation DTO,
serializeTunerFmBandScanJson). Blocks for the whole sweep like the existing
/api/tuner/scan.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0178rASQ6ZETPMUamvpoR2KR
This commit is contained in:
2026-08-18 07:50:28 +02:00
co-authored by Claude Sonnet 5
parent 8a69cbed08
commit 3a10ed75aa
6 changed files with 306 additions and 0 deletions
@@ -139,6 +139,29 @@ namespace {
return EXIT_SUCCESS;
}
[[nodiscard]] int runTunerFmBandScanSerialiseTest()
{
core::TunerFmScannedStation withName{
*core::FrequencyKHz::tryFromKhz(98300U), 12, 13,
core::BroadcastLabel::tryFromChipBytes("RADIO 1")};
core::TunerFmScannedStation withoutName{
*core::FrequencyKHz::tryFromKhz(105500U), -4, -2, std::nullopt};
const std::string json =
core::serializeTunerFmBandScanJson({withName, withoutName});
if (!expectEqual(
json,
R"({"stations":[{"frequency_khz":98300,"rssi_dbuv":12,"snr_db":13,"station_name":"RADIO 1"},{"frequency_khz":105500,"rssi_dbuv":-4,"snr_db":-2}]})")) {
return EXIT_FAILURE;
}
const std::string emptyJson = core::serializeTunerFmBandScanJson({});
if (!expectEqual(emptyJson, R"({"stations":[]})")) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
[[nodiscard]] int runTunerStatusMetadataSerialiseTest()
{
core::TunerStatus status = {};
@@ -240,5 +263,8 @@ int main()
if (runTunerSeekParseTest() != EXIT_SUCCESS) {
return EXIT_FAILURE;
}
if (runTunerFmBandScanSerialiseTest() != EXIT_SUCCESS) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}