Phase 3 (batch 31a): shared TDeviceStore for saved+discovered devices

Introduce DeviceStore.pas (TDeviceStore) as the single source of truth for
saved devices (hpsdr_devices.ini CRUD + autostart) and the current discovery
list. The controller owns one instance (created/freed in its ctor/dtor);
desktop and (later) web frontends edit/render through it so the lists never
diverge.

Refactor TDeviceDialog to use a TDeviceStore reference instead of its own
arrays + ini code. MainForm wires FDeviceDialog.Store to the controller's
store, routes discovery results (DoAddDevice) and the preload-rate lookup
through it (TDiscoveredDevice now carries the MAC), and drops the now-unused
FDevices/TDeviceItem. Behavior-preserving for the desktop dialog.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Uladzimir Karpenka
2026-06-08 12:36:43 +03:00
co-authored by Claude Opus 4.8
parent 783c8976c9
commit 7f7f429515
4 changed files with 368 additions and 212 deletions
+20 -36
View File
@@ -41,6 +41,7 @@ uses
FlatEdit, FMRepeater,
ChannelStore, ChannelsForm,
PowerInhibit,
DeviceStore,
RadioController;
const
@@ -107,11 +108,6 @@ const
LEFT_PANEL_BTN_GAP = 2;
type
TDeviceItem = record
Dev: THPSDRDevice;
Display: string;
end;
{ TMainForm }
TMainForm = class(TForm)
private
@@ -124,8 +120,7 @@ type
FSyncingFromController: Boolean;
// ---- Network ----
FDevices: array of TDeviceItem;
FDeviceCount: Integer;
// Список устройств (saved+discovered) → FController.FDeviceStore (общий с web).
FDeviceDialog: TDeviceDialog;
FPendingIP: string; // IP устройства для подключения
FVfoOverlay: TVfoOverlay; // накладка SmartSDR-стиль на спектре
@@ -1039,8 +1034,8 @@ begin
FController.FLastSupplyV:= -1;
FController.FLastSupplyA:= -1;
FController.FLastPLLLock:= False;
FDeviceCount := 0;
FDeviceDialog := TDeviceDialog.Create(Self);
FDeviceDialog.Store := FController.FDeviceStore;
FDeviceDialog.OnDiscover := BtnDiscoverFromDialog;
FVfoOverlay := TVfoOverlay.Create(Self);
FVfoOverlay.OnSelect := OnModeFilterSelect;
@@ -3285,19 +3280,12 @@ begin
end;
procedure TMainForm.DoAddDevice(const Dev: THPSDRDevice; const Entry: string);
var
Idx: Integer;
begin
Idx := Length(FDevices);
SetLength(FDevices, Idx + 1);
FDevices[Idx].Dev := Dev;
FDevices[Idx].Display := Entry;
Inc(FDeviceCount);
// Найденное устройство → общий store (через диалог, который пишет store +
// рендерит список). MAC нужен для preload-rate lookup в BtnStartStopClick.
if Assigned(FDeviceDialog) then
FDeviceDialog.AddDiscovered(Dev.IPAddress, Entry, Dev.BoardType);
SetStatusText(2, Format('Found: %s', [Dev.IPAddress]));
FDeviceDialog.AddDiscovered(Dev.IPAddress, Entry, Dev.BoardType, Dev.MAC);
SetStatusText(2, Format('Found: %s', [Dev.IPAddress]));
end;
@@ -3457,10 +3445,7 @@ begin
if DDCIdx = -1 then
begin
if Assigned(FDeviceDialog) then
begin
FDeviceDialog.ClearDiscovered;
FDeviceDialog.AddDiscovered('', '-- no device found --');
end;
FDeviceDialog.NoDevicesFound;
SetStatusText(2, 'No hardware found');
end
else
@@ -3555,6 +3540,7 @@ begin
// Открываем диалог выбора устройства
if not Assigned(FDeviceDialog) then
FDeviceDialog := TDeviceDialog.Create(Self);
FDeviceDialog.Store := FController.FDeviceStore;
FDeviceDialog.OnDiscover := BtnDiscoverFromDialog;
if FLightTheme then FDeviceDialog.SetTheme(LightTheme)
else FDeviceDialog.SetTheme(DarkTheme);
@@ -3567,8 +3553,7 @@ end;
procedure TMainForm.BtnDiscoverFromDialog(Sender: TObject);
// Запускается когда пользователь нажимает DISCOVER внутри диалога
begin
SetLength(FDevices, 0);
FDeviceCount := 0;
FController.FDeviceStore.ClearDiscovered;
SetStatusText(2, 'Discovering...');
FController.FNetwork.DirectIP := '';
TDiscoverThread.Create(FController.FNetwork, Self);
@@ -3576,10 +3561,8 @@ end;
procedure TMainForm.BtnStartStopClick(Sender: TObject);
var
Idx, i: Integer;
i: Integer;
Dev: THPSDRDevice;
GenPkt: TGeneralPacket;
G_Settings: TGlobalSettings;
PreG: TGlobalSettings;
PreBands: array[0..CFG_BAND_COUNT-1] of TBandSettings;
PreloadRate: Integer;
@@ -3641,6 +3624,7 @@ begin
begin
if not Assigned(FDeviceDialog) then
FDeviceDialog := TDeviceDialog.Create(Self);
FDeviceDialog.Store := FController.FDeviceStore;
FDeviceDialog.OnDiscover := BtnDiscoverFromDialog;
if FLightTheme then FDeviceDialog.SetTheme(LightTheme)
else FDeviceDialog.SetTheme(DarkTheme);
@@ -3664,14 +3648,14 @@ begin
// создаём WDSPEngine сразу с нужной частотой.
PreloadRate := FController.FSampleRate;
FoundByIP := False;
for i := 0 to High(FDevices) do
if SameText(FDevices[i].Dev.IPAddress, Dev.IPAddress) then
begin
FoundByIP := True;
if FController.FSettings.LoadDevice(FDevices[i].Dev.MAC, PreG, PreBands) and (PreG.SampleRate > 0) then
PreloadRate := PreG.SampleRate;
Break;
end;
i := FController.FDeviceStore.FindDiscoveredByIP(Dev.IPAddress);
if i >= 0 then
begin
FoundByIP := True;
if FController.FSettings.LoadDevice(FController.FDeviceStore.Discovered(i).MAC, PreG, PreBands)
and (PreG.SampleRate > 0) then
PreloadRate := PreG.SampleRate;
end;
if FoundByIP and (PreloadRate > 0) then
begin
FController.FSampleRate := PreloadRate;