mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
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:
@@ -6,6 +6,15 @@ unit BoardUtils;
|
|||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
|
type
|
||||||
|
// Один диапазон плана (имя кнопки + частота по умолчанию). Общий тип для
|
||||||
|
// desktop/web UI — единый источник band-плана через TRadioController.BandPlan.
|
||||||
|
TBandInfo = record
|
||||||
|
Name: string;
|
||||||
|
FreqHz: Double;
|
||||||
|
end;
|
||||||
|
TBandPlanArray = array of TBandInfo;
|
||||||
|
|
||||||
function BoardTypeName(BoardType: Integer): string;
|
function BoardTypeName(BoardType: Integer): string;
|
||||||
// Короткое человекочитаемое имя AD936x-платы по hw_model (Pluto / LibreSDR / прочие).
|
// Короткое человекочитаемое имя AD936x-платы по hw_model (Pluto / LibreSDR / прочие).
|
||||||
function PlutoModelName(const HwModel: string): string;
|
function PlutoModelName(const HwModel: string): string;
|
||||||
@@ -15,6 +24,8 @@ function FreqToBandIdx(Hz: Double; Pluto: Boolean = False): Integer;
|
|||||||
function BandName(Idx: Integer; Pluto: Boolean = False): string;
|
function BandName(Idx: Integer; Pluto: Boolean = False): string;
|
||||||
// Частота по умолчанию при входе в диапазон (если нет сохранённой/в диапазоне).
|
// Частота по умолчанию при входе в диапазон (если нет сохранённой/в диапазоне).
|
||||||
function BandDefaultFreq(Idx: Integer; Pluto: Boolean = False): Double;
|
function BandDefaultFreq(Idx: Integer; Pluto: Boolean = False): Double;
|
||||||
|
// Полный band-план активного бэкенда (имена + дефолтные частоты).
|
||||||
|
function BuildBandPlan(Pluto: Boolean): TBandPlanArray;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@@ -105,4 +116,23 @@ begin
|
|||||||
if Pluto then Result := VU_DEF[Idx] else Result := HF_DEF[Idx];
|
if Pluto then Result := VU_DEF[Idx] else Result := HF_DEF[Idx];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function BuildBandPlan(Pluto: Boolean): TBandPlanArray;
|
||||||
|
var i: Integer;
|
||||||
|
begin
|
||||||
|
SetLength(Result, BAND_COUNT);
|
||||||
|
for i := 0 to BAND_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
if Pluto then
|
||||||
|
begin
|
||||||
|
Result[i].Name := VU_NAMES[i];
|
||||||
|
Result[i].FreqHz := VU_DEF[i];
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Result[i].Name := HF_NAMES[i];
|
||||||
|
Result[i].FreqHz := HF_DEF[i];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
@@ -479,6 +479,7 @@ type
|
|||||||
procedure OnXvtrSettingsChange(const X: TXvtrSettings);
|
procedure OnXvtrSettingsChange(const X: TXvtrSettings);
|
||||||
procedure PushXvtrToWeb;
|
procedure PushXvtrToWeb;
|
||||||
procedure PushRatePresetsToWeb; // backend sample-rate пресеты → web
|
procedure PushRatePresetsToWeb; // backend sample-rate пресеты → web
|
||||||
|
procedure PushBandsToWeb; // backend band-план → web
|
||||||
// XVTR helpers
|
// XVTR helpers
|
||||||
function FindXvtrIdxForFreq(FreqHz: Double): Integer;
|
function FindXvtrIdxForFreq(FreqHz: Double): Integer;
|
||||||
function XvtrTranslate(VisibleHz: Double): Double;
|
function XvtrTranslate(VisibleHz: Double): Double;
|
||||||
@@ -884,6 +885,7 @@ begin
|
|||||||
PushXvtrToWeb;
|
PushXvtrToWeb;
|
||||||
PushDeviceListToWeb; // saved-устройства сразу видны web-overlay
|
PushDeviceListToWeb; // saved-устройства сразу видны web-overlay
|
||||||
PushRatePresetsToWeb; // дефолтный бэкенд до connect; перезапишется на смене
|
PushRatePresetsToWeb; // дефолтный бэкенд до connect; перезапишется на смене
|
||||||
|
PushBandsToWeb;
|
||||||
FillChar(FCATLastGlobal, SizeOf(FCATLastGlobal), 0);
|
FillChar(FCATLastGlobal, SizeOf(FCATLastGlobal), 0);
|
||||||
FCATLastGlobal.CATTcpPort := 19090;
|
FCATLastGlobal.CATTcpPort := 19090;
|
||||||
for i := 0 to 3 do
|
for i := 0 to 3 do
|
||||||
@@ -3685,6 +3687,7 @@ begin
|
|||||||
FSampleRateOverlay.SetCurrentRate(FController.FSampleRate);
|
FSampleRateOverlay.SetCurrentRate(FController.FSampleRate);
|
||||||
end;
|
end;
|
||||||
PushRatePresetsToWeb; // тот же источник зеркалим в web-морду
|
PushRatePresetsToWeb; // тот же источник зеркалим в web-морду
|
||||||
|
PushBandsToWeb; // band-план бэкенда → web (HF ↔ VHF/UHF)
|
||||||
|
|
||||||
// Отдельный Pluto RF-AGC блок под AGC: показываем и сдвигаем панели ниже.
|
// Отдельный Pluto RF-AGC блок под AGC: показываем и сдвигаем панели ниже.
|
||||||
LayoutLeftPanel(Caps.HasHWGain);
|
LayoutLeftPanel(Caps.HasHWGain);
|
||||||
@@ -5375,6 +5378,27 @@ begin
|
|||||||
FWebServer.SetRatePresets(FController.SampleRatePresets);
|
FWebServer.SetRatePresets(FController.SampleRatePresets);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.PushBandsToWeb;
|
||||||
|
// Band-план бэкенда → web (HF / VHF-UHF). Единый источник — FController.BandPlan,
|
||||||
|
// тот же BoardUtils-план, что и для desktop-кнопок (RelabelBands).
|
||||||
|
var
|
||||||
|
Plan: TBandPlanArray;
|
||||||
|
Names: array of string;
|
||||||
|
Freqs: array of Double;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
if FWebServer = nil then Exit;
|
||||||
|
Plan := FController.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;
|
||||||
|
FWebServer.SetBands(Names, Freqs);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TMainForm.PushXvtrToWeb;
|
procedure TMainForm.PushXvtrToWeb;
|
||||||
var
|
var
|
||||||
Arr: TWebXvtrArray;
|
Arr: TWebXvtrArray;
|
||||||
|
|||||||
@@ -547,6 +547,8 @@ type
|
|||||||
// Единый источник пресетов sample-rate для UI (desktop overlay + web).
|
// Единый источник пресетов sample-rate для UI (desktop overlay + web).
|
||||||
// Берётся из caps текущего бэкенда (HPSDR 48k..1536k / Pluto 576k..5760k).
|
// Берётся из caps текущего бэкенда (HPSDR 48k..1536k / Pluto 576k..5760k).
|
||||||
function SampleRatePresets: TBackendRateArray;
|
function SampleRatePresets: TBackendRateArray;
|
||||||
|
// Единый источник band-плана для UI (HF / VHF-UHF по типу бэкенда).
|
||||||
|
function BandPlan: TBandPlanArray;
|
||||||
// True если активный бэкенд — Pluto (VHF/UHF band-план вместо HF).
|
// True если активный бэкенд — Pluto (VHF/UHF band-план вместо HF).
|
||||||
function IsPluto: Boolean;
|
function IsPluto: Boolean;
|
||||||
// Человекочитаемое имя подключённой платы для статус-строки (UI/Web).
|
// Человекочитаемое имя подключённой платы для статус-строки (UI/Web).
|
||||||
@@ -3162,6 +3164,11 @@ begin
|
|||||||
Result := BackendCaps.RatePresets;
|
Result := BackendCaps.RatePresets;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TRadioController.BandPlan: TBandPlanArray;
|
||||||
|
begin
|
||||||
|
Result := BuildBandPlan(IsPluto);
|
||||||
|
end;
|
||||||
|
|
||||||
function TRadioController.IsPluto: Boolean;
|
function TRadioController.IsPluto: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := (FNetwork <> nil) and (FNetwork.Caps.Kind = bkPluto);
|
Result := (FNetwork <> nil) and (FNetwork.Caps.Kind = bkPluto);
|
||||||
|
|||||||
+8
-2
@@ -524,8 +524,10 @@ begin
|
|||||||
'function updSpan(s){SPANS.forEach((hz,i)=>{const b=q("sb"+i);if(b)b.classList.toggle("on",hz===s);});}' +
|
'function updSpan(s){SPANS.forEach((hz,i)=>{const b=q("sb"+i);if(b)b.classList.toggle("on",hz===s);});}' +
|
||||||
'buildSpanButtons();' +
|
'buildSpanButtons();' +
|
||||||
|
|
||||||
'const BAND_N=["160m","80m","60m","40m","30m","20m","17m","15m","12m","10m","6m"];' +
|
// BAND_N/BAND_F строятся из state.bands (HPSDR HF / Pluto VHF-UHF); ниже —
|
||||||
'const BAND_F=[1900000,3750000,5357000,7100000,10125000,14200000,18120000,21200000,24940000,28500000,50150000];' +
|
// bootstrap-значения до первого state. Единый источник — backend в контроллере.
|
||||||
|
'let BAND_N=["160m","80m","60m","40m","30m","20m","17m","15m","12m","10m","6m"];' +
|
||||||
|
'let BAND_F=[1840000,3700000,5357000,7100000,10120000,14200000,18130000,21300000,24940000,28400000,50150000];' +
|
||||||
// XVTR-band list, обновляется из state ("xvtr_bands":[{idx,name},...]).
|
// XVTR-band list, обновляется из state ("xvtr_bands":[{idx,name},...]).
|
||||||
// Активное значение — "xvtr_current" (-1 = HF). В <select> используем
|
// Активное значение — "xvtr_current" (-1 = HF). В <select> используем
|
||||||
// значения "h<n>" для HF и "x<idx>" для XVTR, чтобы различать.
|
// значения "h<n>" для HF и "x<idx>" для XVTR, чтобы различать.
|
||||||
@@ -689,6 +691,10 @@ begin
|
|||||||
// Пресеты sample-rate сменились (другой бэкенд) — перестраиваем span-кнопки.
|
// Пресеты sample-rate сменились (другой бэкенд) — перестраиваем span-кнопки.
|
||||||
'if(msg.rate_presets!=null&&Array.isArray(msg.rate_presets)&&msg.rate_presets.length){' +
|
'if(msg.rate_presets!=null&&Array.isArray(msg.rate_presets)&&msg.rate_presets.length){' +
|
||||||
'if(JSON.stringify(msg.rate_presets)!==JSON.stringify(SPANS)){SPANS=msg.rate_presets;buildSpanButtons();}}' +
|
'if(JSON.stringify(msg.rate_presets)!==JSON.stringify(SPANS)){SPANS=msg.rate_presets;buildSpanButtons();}}' +
|
||||||
|
// Band-план сменился (другой бэкенд: HF↔VHF/UHF) — перестраиваем band-selector.
|
||||||
|
'if(msg.bands!=null&&Array.isArray(msg.bands)&&msg.bands.length){' +
|
||||||
|
'const nn=msg.bands.map(function(b){return b.name;});' +
|
||||||
|
'if(JSON.stringify(nn)!==JSON.stringify(BAND_N)){BAND_N=nn;BAND_F=msg.bands.map(function(b){return b.freq;});rebuildBandSel();}}' +
|
||||||
// Обновляем localCenter/localSpan из сервера только когда пользователь не тянет
|
// Обновляем localCenter/localSpan из сервера только когда пользователь не тянет
|
||||||
'if(!dragging&&Date.now()-wheelActiveTs>300){' +
|
'if(!dragging&&Date.now()-wheelActiveTs>300){' +
|
||||||
// В CTUN без DUP: TX-спектр WDSP центрирован по vfo_a_hz, а не по DDC LO.
|
// В CTUN без DUP: TX-спектр WDSP центрирован по vfo_a_hz, а не по DDC LO.
|
||||||
|
|||||||
+36
-3
@@ -298,6 +298,8 @@ type
|
|||||||
FXvtrBands: TWebXvtrArray; // список enabled XVTR (для web-UI)
|
FXvtrBands: TWebXvtrArray; // список enabled XVTR (для web-UI)
|
||||||
FDevices: TWebDeviceArray; // saved+discovered устройства (для web-overlay)
|
FDevices: TWebDeviceArray; // saved+discovered устройства (для web-overlay)
|
||||||
FRatePresets: array of Integer; // sample-rate пресеты текущего бэкенда (для span-кнопок)
|
FRatePresets: array of Integer; // sample-rate пресеты текущего бэкенда (для span-кнопок)
|
||||||
|
FBandNames: array of string; // band-план текущего бэкенда (имена кнопок)
|
||||||
|
FBandFreqs: array of Double; // band-план: дефолтные частоты (для подсветки selector)
|
||||||
FCurrentXvtr: Integer; // -1 = HF, иначе индекс активного XVTR
|
FCurrentXvtr: Integer; // -1 = HF, иначе индекс активного XVTR
|
||||||
FOnXvtrBand: TWebCmdXvtrBand;
|
FOnXvtrBand: TWebCmdXvtrBand;
|
||||||
|
|
||||||
@@ -394,6 +396,7 @@ type
|
|||||||
procedure SetXvtrBands(const ABands: TWebXvtrArray; ACurrent: Integer);
|
procedure SetXvtrBands(const ABands: TWebXvtrArray; ACurrent: Integer);
|
||||||
procedure SetDeviceList(const ADevices: TWebDeviceArray);
|
procedure SetDeviceList(const ADevices: TWebDeviceArray);
|
||||||
procedure SetRatePresets(const ARates: array of Integer);
|
procedure SetRatePresets(const ARates: array of Integer);
|
||||||
|
procedure SetBands(const ANames: array of string; const AFreqs: array of Double);
|
||||||
property OnSpan: TWebCmdSpan read FOnSpan write FOnSpan;
|
property OnSpan: TWebCmdSpan read FOnSpan write FOnSpan;
|
||||||
property OnVolume: TWebCmdVolume read FOnVolume write FOnVolume;
|
property OnVolume: TWebCmdVolume read FOnVolume write FOnVolume;
|
||||||
property OnWfAGC: TWebCmdWfAGC read FOnWfAGC write FOnWfAGC;
|
property OnWfAGC: TWebCmdWfAGC read FOnWfAGC write FOnWfAGC;
|
||||||
@@ -539,6 +542,10 @@ begin
|
|||||||
SetLength(FXvtrBands, 0);
|
SetLength(FXvtrBands, 0);
|
||||||
// Bootstrap-набор рейтов (до connect): хост перезапишет под бэкенд (HPSDR/Pluto).
|
// Bootstrap-набор рейтов (до connect): хост перезапишет под бэкенд (HPSDR/Pluto).
|
||||||
SetRatePresets([48000, 96000, 192000, 384000, 768000, 1536000]);
|
SetRatePresets([48000, 96000, 192000, 384000, 768000, 1536000]);
|
||||||
|
// Bootstrap band-план (HF): хост перезапишет под бэкенд на connect.
|
||||||
|
SetBands(['160m','80m','60m','40m','30m','20m','17m','15m','12m','10m','6m'],
|
||||||
|
[1840000,3700000,5357000,7100000,10120000,14200000,
|
||||||
|
18130000,21300000,24940000,28400000,50150000]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWebServer.SetXvtrBands(const ABands: TWebXvtrArray; ACurrent: Integer);
|
procedure TWebServer.SetXvtrBands(const ABands: TWebXvtrArray; ACurrent: Integer);
|
||||||
@@ -583,6 +590,22 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TWebServer.SetBands(const ANames: array of string; const AFreqs: array of Double);
|
||||||
|
// Band-план текущего бэкенда (из TRadioController). Web строит band-selector из
|
||||||
|
// него — HPSDR (HF) и Pluto (VHF/UHF) имеют разные планы.
|
||||||
|
var i: Integer;
|
||||||
|
begin
|
||||||
|
FStateLock.Enter;
|
||||||
|
try
|
||||||
|
SetLength(FBandNames, Length(ANames));
|
||||||
|
SetLength(FBandFreqs, Length(AFreqs));
|
||||||
|
for i := 0 to High(ANames) do FBandNames[i] := ANames[i];
|
||||||
|
for i := 0 to High(AFreqs) do FBandFreqs[i] := AFreqs[i];
|
||||||
|
finally
|
||||||
|
FStateLock.Leave;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
destructor TWebServer.Destroy;
|
destructor TWebServer.Destroy;
|
||||||
begin
|
begin
|
||||||
Stop;
|
Stop;
|
||||||
@@ -1561,7 +1584,7 @@ const
|
|||||||
('LSB','USB','DSB','CWL','CWU','FM','AM','SAM');
|
('LSB','USB','DSB','CWL','CWU','FM','AM','SAM');
|
||||||
var
|
var
|
||||||
FS: TFormatSettings;
|
FS: TFormatSettings;
|
||||||
XvtrJson, DevJson, RateJson: string;
|
XvtrJson, DevJson, RateJson, BandJson: string;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
FS := DefaultFormatSettings;
|
FS := DefaultFormatSettings;
|
||||||
@@ -1576,6 +1599,16 @@ begin
|
|||||||
RateJson := RateJson + IntToStr(FRatePresets[i]);
|
RateJson := RateJson + IntToStr(FRatePresets[i]);
|
||||||
end;
|
end;
|
||||||
RateJson := RateJson + ']';
|
RateJson := RateJson + ']';
|
||||||
|
// Сборка массива bands: [{"name":"6m","freq":50150000},...] (band-selector web).
|
||||||
|
BandJson := '[';
|
||||||
|
for i := 0 to High(FBandNames) do
|
||||||
|
begin
|
||||||
|
if i > 0 then BandJson := BandJson + ',';
|
||||||
|
BandJson := BandJson +
|
||||||
|
Format('{"name":"%s","freq":%.0f}',
|
||||||
|
[JsonEscape(FBandNames[i]), FBandFreqs[i]], FS);
|
||||||
|
end;
|
||||||
|
BandJson := BandJson + ']';
|
||||||
// Сборка массива xvtr_bands: [{"idx":0,"name":"2m"},...]
|
// Сборка массива xvtr_bands: [{"idx":0,"name":"2m"},...]
|
||||||
XvtrJson := '[';
|
XvtrJson := '[';
|
||||||
for i := 0 to High(FXvtrBands) do
|
for i := 0 to High(FXvtrBands) do
|
||||||
@@ -1613,7 +1646,7 @@ begin
|
|||||||
'"status_text":"%s","board_text":"%s","ip_text":"%s","supply_text":"%s",' +
|
'"status_text":"%s","board_text":"%s","ip_text":"%s","supply_text":"%s",' +
|
||||||
'"pll_text":"%s","rx_text":"%s","tx_text":"%s","seq_text":"%s",' +
|
'"pll_text":"%s","rx_text":"%s","tx_text":"%s","seq_text":"%s",' +
|
||||||
'"xvtr_current":%d,"xvtr_bands":%s,"freq_mhz_digits":%d,' +
|
'"xvtr_current":%d,"xvtr_bands":%s,"freq_mhz_digits":%d,' +
|
||||||
'"fmstep_idx":%d,"devices":%s,"rate_presets":%s}',
|
'"fmstep_idx":%d,"devices":%s,"rate_presets":%s,"bands":%s}',
|
||||||
[FFreq, FVfoB, FActiveVfo,
|
[FFreq, FVfoB, FActiveVfo,
|
||||||
FMode, MODE_N[FMode mod 8],
|
FMode, MODE_N[FMode mod 8],
|
||||||
FFilterIdx, FFilterBW,
|
FFilterIdx, FFilterBW,
|
||||||
@@ -1642,7 +1675,7 @@ begin
|
|||||||
JsonEscape(FSupplyText), JsonEscape(FPLLText), JsonEscape(FRXText),
|
JsonEscape(FSupplyText), JsonEscape(FPLLText), JsonEscape(FRXText),
|
||||||
JsonEscape(FTXText), JsonEscape(FSeqText),
|
JsonEscape(FTXText), JsonEscape(FSeqText),
|
||||||
FCurrentXvtr, XvtrJson, FFreqMhzDigits,
|
FCurrentXvtr, XvtrJson, FFreqMhzDigits,
|
||||||
FFMStepIdx, DevJson, RateJson
|
FFMStepIdx, DevJson, RateJson, BandJson
|
||||||
], FS);
|
], FS);
|
||||||
finally
|
finally
|
||||||
FStateLock.Leave;
|
FStateLock.Leave;
|
||||||
|
|||||||
+22
-2
@@ -28,7 +28,7 @@ uses
|
|||||||
{$IFDEF UNIX}cthreads, BaseUnix,{$ENDIF}
|
{$IFDEF UNIX}cthreads, BaseUnix,{$ENDIF}
|
||||||
Classes, SysUtils,
|
Classes, SysUtils,
|
||||||
RadioController, WebServer, WebAdapter,
|
RadioController, WebServer, WebAdapter,
|
||||||
HPSDRNetwork, Settings, WDSP, PlatformUtils, DeviceStore;
|
HPSDRNetwork, Settings, WDSP, PlatformUtils, DeviceStore, BoardUtils;
|
||||||
|
|
||||||
const
|
const
|
||||||
DAEMON_SPEC_WIDTH = 1024; // ширина спектра для StartRunning (web-буфер = 1024)
|
DAEMON_SPEC_WIDTH = 1024; // ширина спектра для StartRunning (web-буфер = 1024)
|
||||||
@@ -56,6 +56,7 @@ type
|
|||||||
procedure PushDeviceList;
|
procedure PushDeviceList;
|
||||||
procedure PushXvtr;
|
procedure PushXvtr;
|
||||||
procedure PushRatePresets; // sample-rate пресеты бэкенда → web
|
procedure PushRatePresets; // sample-rate пресеты бэкенда → web
|
||||||
|
procedure PushBands; // band-план бэкенда → web
|
||||||
// Входящие web-команды (из WS-потока): запоминаем параметр и маршалим в Sync*.
|
// Входящие web-команды (из WS-потока): запоминаем параметр и маршалим в Sync*.
|
||||||
procedure WebRun(On_: Boolean);
|
procedure WebRun(On_: Boolean);
|
||||||
procedure WebConnect(const IP: string);
|
procedure WebConnect(const IP: string);
|
||||||
@@ -197,7 +198,7 @@ begin
|
|||||||
// выходные web-списки, которых нет в периодическом PushState.
|
// выходные web-списки, которых нет в периодическом PushState.
|
||||||
case Field of
|
case Field of
|
||||||
rfDeviceList: PushDeviceList; // discovered обновился
|
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;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -297,6 +298,24 @@ begin
|
|||||||
FWeb.SetRatePresets(FCtrl.SampleRatePresets);
|
FWeb.SetRatePresets(FCtrl.SampleRatePresets);
|
||||||
end;
|
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-поток) → маршалинг в главный поток ---
|
// --- Входящие web-команды (WS-поток) → маршалинг в главный поток ---
|
||||||
|
|
||||||
procedure THeadlessHost.WebRun(On_: Boolean);
|
procedure THeadlessHost.WebRun(On_: Boolean);
|
||||||
@@ -389,6 +408,7 @@ begin
|
|||||||
Log('Web control on http://' + WebCfg.BindAddr + ':' + IntToStr(WebCfg.Port));
|
Log('Web control on http://' + WebCfg.BindAddr + ':' + IntToStr(WebCfg.Port));
|
||||||
PushDeviceList;
|
PushDeviceList;
|
||||||
PushRatePresets; // дефолтный бэкенд (HPSDR) до connect; перезапишется на смене
|
PushRatePresets; // дефолтный бэкенд (HPSDR) до connect; перезапишется на смене
|
||||||
|
PushBands;
|
||||||
|
|
||||||
// FRunning ставим ДО autostart: первый WDSP-open может занять время, и если за
|
// FRunning ставим ДО autostart: первый WDSP-open может занять время, и если за
|
||||||
// него прилетит SIGINT (RequestStop→FRunning:=False), цикл сразу завершится, а
|
// него прилетит SIGINT (RequestStop→FRunning:=False), цикл сразу завершится, а
|
||||||
|
|||||||
Reference in New Issue
Block a user