mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
feat(tci): TCI 2.0 — EWSDR как сервер (команды и уведомления)
Протокол Expert Electronics поверх WebSocket, порт 40001. EWSDR слушает, клиенты — логгеры, скиммеры, цифровые программы. - TCIProtocol.pas — чистый слой протокола: разбор/сборка `имя:арг;`, экранирование `^ ~ *`, словарь видов связи, пересчёт громкости в дБ. - TCIServer.pas — WS-сервер поверх WebUtils/WsClient: accept-поток, поток на клиента, HTTP-Upgrade, фреймы, рассылка, тик 20 мс. - TCIAdapter.pas — мост к TRadioController по схеме CAT: геттеры читают поля напрямую, сеттеры через Invoke, уведомления через AddStateListener. Маппинг: приёмник TCI = панадаптер, канал A/B = VFO A/B (пан 0) либо первый/второй слайс (паны 1..). Попутно: TRadioController.RemoveStateListener (адаптер умирает раньше контроллера) и TDXSpotStore.RemoveCall (spot_delete). Настройки — секция "tci" в settings.json (умолчание: выключено, 127.0.0.1, так как авторизации в протоколе нет) и вкладка Advanced → TCI Server. Бинарные потоки (IQ/аудио) — этап 2. Статус, таблица команд и список осознанных эхо-заглушек — в doc/TCI.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1185,6 +1185,9 @@ type
|
||||
// Доп. наблюдатели состояния (помимо единственного OnStateChanged, который
|
||||
// занимает MainForm). Нужны CAT/Andromeda для push индикаторов панели.
|
||||
procedure AddStateListener(L: TRadioStateEvent);
|
||||
// Снять наблюдателя. Обязателен для тех, кто умирает раньше контроллера
|
||||
// (TCI-адаптер): иначе Changed() позовёт метод освобождённого объекта.
|
||||
procedure RemoveStateListener(L: TRadioStateEvent);
|
||||
// Пост-тюн хук: вызывается в КОНЦЕ SetVfoA (после Changed(rfVfoA), т.е. вне
|
||||
// рендера) — сюда вешается канальная оркестрация (ChannelController.OnVfoTuned),
|
||||
// чтобы любой путь тюнинга (desktop/web/CAT/энкодер) был канал-aware headless.
|
||||
@@ -1447,6 +1450,21 @@ begin
|
||||
FStateListeners[High(FStateListeners)] := L;
|
||||
end;
|
||||
|
||||
procedure TRadioController.RemoveStateListener(L: TRadioStateEvent);
|
||||
var i, j: Integer;
|
||||
begin
|
||||
if not Assigned(L) then Exit;
|
||||
for i := 0 to High(FStateListeners) do
|
||||
if (TMethod(FStateListeners[i]).Code = TMethod(L).Code) and
|
||||
(TMethod(FStateListeners[i]).Data = TMethod(L).Data) then
|
||||
begin
|
||||
for j := i to High(FStateListeners) - 1 do
|
||||
FStateListeners[j] := FStateListeners[j + 1];
|
||||
SetLength(FStateListeners, Length(FStateListeners) - 1);
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TRadioController.PushNetworkState;
|
||||
// Полный HP-кадр в радио: RX/TX частоты (через трансвертор), drive, состояние
|
||||
// MOX. Вызывается командами, которые меняют центр/частоту/репитер-сдвиг.
|
||||
|
||||
Reference in New Issue
Block a user