Phase 3 (WA3): move outgoing web state-mirror into the web adapter

The per-tick PushSpectrum mirror (status strings + ~40 state values + spectrum/
waterfall buffers) moves out of SpectrumTimerTick into TWebAdapter.PushState,
which reads FController for everything and takes the pixel buffers as params.
MainForm's timer now just calls FWebAdapter.PushState(FSpectrumBuf, FWaterfallBuf).

Server lifecycle/ownership stays in MainForm for now — it's still driven by the
remaining host-coupled handlers (PushXvtrToWeb, device CRUD); ownership transfer
completes when those move.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Uladzimir Karpenka
2026-06-08 20:36:01 +03:00
co-authored by Claude Opus 4.8
parent e5a13096dc
commit e1ecf947b8
2 changed files with 88 additions and 85 deletions
+4 -84
View File
@@ -3054,8 +3054,6 @@ procedure TMainForm.SpectrumTimerTick(Sender: TObject);
var
NowTick: QWord;
ElapsedTick: QWord;
WebStatusText, WebBoardText, WebIPText, WebSupplyText: string;
WebPLLText, WebRXText, WebTXText, WebSeqText: string;
begin
// Синхронизируем размеры если размер панели изменился (после ресайза).
// Важно: проверяем только видимые панели — когда спектр скрыт,
@@ -3195,88 +3193,10 @@ begin
FSpectrumDirty := False;
end;
// Пушим текущее состояние в веб-клиенты (если есть)
if Assigned(FWebServer) then
begin
if FController.FNetwork.Connected then
begin
if FController.FRunning then
WebStatusText := 'Running'
else
WebStatusText := 'Connected';
WebBoardText := 'Board: ' + BoardTypeName(FController.FNetwork.Device.BoardType);
WebIPText := 'IP: ' + FController.FNetwork.Device.IPAddress;
end
else
begin
WebStatusText := 'Disconnected';
WebBoardText := 'Board --';
WebIPText := 'IP --';
end;
if not FController.FRunning then
begin
WebSupplyText := 'Supply --';
WebPLLText := 'PLL --';
end
else
begin
if FController.FLastPLLLock then
WebPLLText := 'PLL OK'
else
WebPLLText := 'PLL?';
if not BoardSupportsSupplyVoltage(FController.FNetwork.Device.BoardType) then
WebSupplyText := 'Supply n/a'
else if FController.FLastSupplyV >= 0 then
begin
if FController.FLastSupplyA >= 0 then
WebSupplyText := Format('Supply %.1fV %.1fA', [FController.FLastSupplyV, FController.FLastSupplyA])
else
WebSupplyText := Format('Supply %.1fV', [FController.FLastSupplyV]);
end
else
WebSupplyText := 'Supply --';
end;
if FController.FRunning then
WebRXText := 'RX running'
else
WebRXText := 'RX idle';
if FController.FTuning then
WebTXText := 'TX tune'
else if FController.FTransmitting then
WebTXText := 'TX active'
else
WebTXText := 'TX idle';
if FController.FSeqErrorCount > 0 then
WebSeqText := Format('SEQ ERR DDC%d', [FController.FLastSeqErrorDDC])
else if FController.FRunning then
WebSeqText := 'SEQ OK'
else
WebSeqText := 'SEQ --';
FWebServer.PushSpectrum(
FSpectrumBuf, 1024,
FWaterfallBuf,
FController.FLastSMeter,
FController.FVfoA, FController.FMode, FController.FFilterBW, FController.FAGCMode, FController.FAGCTop,
FController.FSpanHz, FController.FVolume,
FController.FWfAGCEnabled, FController.FWfNFEnabled,
FController.FCurrentBand,
FController.FRunning and FController.FNetwork.Connected,
FController.FRunning, FController.FMuted, FController.FCTun,
FController.FNRMode, FController.FNBMode, FController.FSNB, FController.FANF,
FController.FCenterFreq, FController.FFilter,
FController.FVfoB, FController.FActiveVfo,
FController.FTransmitting, FController.FDrivePercent,
FController.FAtten, FController.FTuning, FController.FDisplayDuplex,
FController.FLastFwdW, FController.FLastSWR, FController.FPAMaxPower,
WebStatusText, WebBoardText, WebIPText, WebSupplyText,
WebPLLText, WebRXText, WebTXText, WebSeqText);
end;
// Исходящее зеркало состояния + спектр/водопад в web — в адаптере (читает
// FController; буферы пикселей — у нас). Сервер сам гейтит по FRunning.
if Assigned(FWebAdapter) then
FWebAdapter.PushState(FSpectrumBuf, FWaterfallBuf);
end;
// ===========================================================================