feat: unify band plan across desktop + web UIs

Web band selector was hardcoded to the HF plan, so on Pluto it showed
160m..6m instead of the VHF/UHF plan and highlighted the wrong entry
(band switching itself already worked: web sends idx, controller maps it
via the IsPluto plan). Mirror the sample-rate unification.

Single source of truth = BoardUtils -> controller:
- BoardUtils: TBandInfo/TBandPlanArray + BuildBandPlan(Pluto).
- TRadioController.BandPlan returns BuildBandPlan(IsPluto).

Both UIs derive from it:
- Desktop already plan-aware (RelabelBands + RestoreBand) - unchanged.
- Web: WebServer.SetBands + "bands" in state JSON; hosts push
  BandPlan on connect/startup; JS builds the band selector from
  state.bands (BAND_N/BAND_F now dynamic).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 14:01:23 +03:00
co-authored by Claude Opus 4.8
parent 6b695ce756
commit 4749cf0cbc
6 changed files with 127 additions and 7 deletions
+22 -2
View File
@@ -28,7 +28,7 @@ uses
{$IFDEF UNIX}cthreads, BaseUnix,{$ENDIF}
Classes, SysUtils,
RadioController, WebServer, WebAdapter,
HPSDRNetwork, Settings, WDSP, PlatformUtils, DeviceStore;
HPSDRNetwork, Settings, WDSP, PlatformUtils, DeviceStore, BoardUtils;
const
DAEMON_SPEC_WIDTH = 1024; // ширина спектра для StartRunning (web-буфер = 1024)
@@ -56,6 +56,7 @@ type
procedure PushDeviceList;
procedure PushXvtr;
procedure PushRatePresets; // sample-rate пресеты бэкенда → web
procedure PushBands; // band-план бэкенда → web
// Входящие web-команды (из WS-потока): запоминаем параметр и маршалим в Sync*.
procedure WebRun(On_: Boolean);
procedure WebConnect(const IP: string);
@@ -197,7 +198,7 @@ begin
// выходные web-списки, которых нет в периодическом PushState.
case Field of
rfDeviceList: PushDeviceList; // discovered обновился
rfXvtr, rfDevice: begin PushXvtr; PushDeviceList; PushRatePresets; end; // connect / xvtr / backend
rfXvtr, rfDevice: begin PushXvtr; PushDeviceList; PushRatePresets; PushBands; end; // connect / xvtr / backend
end;
end;
@@ -297,6 +298,24 @@ begin
FWeb.SetRatePresets(FCtrl.SampleRatePresets);
end;
procedure THeadlessHost.PushBands;
var
Plan: TBandPlanArray;
Names: array of string;
Freqs: array of Double;
i: Integer;
begin
Plan := FCtrl.BandPlan;
SetLength(Names, Length(Plan));
SetLength(Freqs, Length(Plan));
for i := 0 to High(Plan) do
begin
Names[i] := Plan[i].Name;
Freqs[i] := Plan[i].FreqHz;
end;
FWeb.SetBands(Names, Freqs);
end;
// --- Входящие web-команды (WS-поток) → маршалинг в главный поток ---
procedure THeadlessHost.WebRun(On_: Boolean);
@@ -389,6 +408,7 @@ begin
Log('Web control on http://' + WebCfg.BindAddr + ':' + IntToStr(WebCfg.Port));
PushDeviceList;
PushRatePresets; // дефолтный бэкенд (HPSDR) до connect; перезапишется на смене
PushBands;
// FRunning ставим ДО autostart: первый WDSP-open может занять время, и если за
// него прилетит SIGINT (RequestStop→FRunning:=False), цикл сразу завершится, а