feat: pluto telemetry — show both temperatures (transceiver + Zynq SoC)

Pluto exposes two temperature sensors: the AD9361 transceiver
(ad9361-phy temp0/input, milli-°C) and the Zynq SoC/FPGA (xadc temp0,
raw+offset+scale → C = (raw+offset)*scale/1000). Only the former was
read. Now both are read and shown as "Temp 37/53C" (chip/SoC) in the
desktop status bar and web UI.

- ReadTelemetry gains an out SocTempC param (base + Pluto override);
  Pluto reads xadc via the IIO context.
- Controller stores FLastPlutoSocTempC; SoC temp validated with a
  plausibility window (no slew-limit — stable local sensor, unlike the
  AD9361 sensor that spikes during mid-conversion).
- Status formatting handles one or both temps in MainForm and WebAdapter.
- Widen desktop status-bar field 3 (150→190) so both temps + RSSI fit;
  web layout unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 19:10:07 +03:00
co-authored by Claude Opus 4.8
parent 63c8c91152
commit 6375092741
6 changed files with 79 additions and 32 deletions
+15 -7
View File
@@ -279,9 +279,10 @@ type
// ---- Телеметрия (наполняется в Фазе 3/4 вместе с сетевыми колбэками) ----
FLastSMeter, FLastFwdW, FLastSWR, FLastSupplyV, FLastSupplyA: Double;
FLastPLLLock: Boolean;
// Pluto-телеметрия (нет HP-status): температура чипа °C / RSSI приёмника дБ.
// Опрашиваются ServicePlutoTelemetry с UI-таймера; TELEMETRY_NONE = нет данных.
FLastPlutoTempC, FLastPlutoRSSIdB: Double;
// Pluto-телеметрия (нет HP-status): температура трансивера °C / Zynq SoC °C /
// RSSI приёмника дБ. Опрашиваются ServicePlutoTelemetry с UI-таймера;
// TELEMETRY_NONE = нет данных.
FLastPlutoTempC, FLastPlutoSocTempC, FLastPlutoRSSIdB: Double;
FPlutoTeleTick: QWord; // GetTickCount64 последнего опроса (троттлинг)
FPlutoTempBad: Integer; // подряд отброшенных выбросов температуры (анти-залипание)
@@ -602,7 +603,8 @@ begin
FFMStepOn := True;
FLocalAudio := True; // GUI: звук на локальную карту; демон выключит явно
FLastSMeter := -130; FLastSWR := 1; FLastSupplyV := -1; FLastSupplyA := -1;
FLastPlutoTempC := TELEMETRY_NONE; FLastPlutoRSSIdB := TELEMETRY_NONE;
FLastPlutoTempC := TELEMETRY_NONE; FLastPlutoSocTempC := TELEMETRY_NONE;
FLastPlutoRSSIdB := TELEMETRY_NONE;
FPlutoTeleTick := 0; FPlutoTempBad := 0;
FillChar(FDevMAC, SizeOf(FDevMAC), 0);
end;
@@ -2809,7 +2811,8 @@ begin
end;
FRXPacketCount := 0;
FActiveDDC := 0;
FLastPlutoTempC := TELEMETRY_NONE; FLastPlutoRSSIdB := TELEMETRY_NONE;
FLastPlutoTempC := TELEMETRY_NONE; FLastPlutoSocTempC := TELEMETRY_NONE;
FLastPlutoRSSIdB := TELEMETRY_NONE;
FPlutoTeleTick := 0; FPlutoTempBad := 0;
Changed(rfRunning); // безусловный сброс run-кнопки/MOX.Enabled/sleep (как старый хвост STOP)
end;
@@ -3201,14 +3204,14 @@ const
TEMP_STEP_C = 12.0; // макс. физичный шаг между опросами (тепловая инерция чипа)
TEMP_FORCE = 3; // принять «выброс», если держится N раз подряд (не залипаем)
var
t, r: Double;
t, s, r: Double;
now_: QWord;
begin
if (FNetwork = nil) or (not FRunning) or (FNetwork.Caps.Kind <> bkPluto) then Exit;
now_ := GetTickCount64;
if (FPlutoTeleTick <> 0) and (now_ - FPlutoTeleTick < POLL_MS) then Exit;
FPlutoTeleTick := now_;
if not FNetwork.ReadTelemetry(t, r) then Exit;
if not FNetwork.ReadTelemetry(t, s, r) then Exit;
// Температура: датчик AD9361 иногда отдаёт мусор (мид-конверсия / контеншн на
// USB-контексте с RX-потоком) — наблюдалось редкое -15 °C. Фильтруем: жёсткое
@@ -3232,6 +3235,11 @@ begin
// вне окна правдоподобия — молча отбрасываем, держим прошлое валидное значение
end;
// Температура Zynq SoC (xadc): стабильный локальный датчик (не подвержен мусору
// мид-конверсии AD9361) — достаточно окна правдоподобия без slew-limit.
if (s > TELEMETRY_NONE) and (s >= TEMP_MIN_C) and (s <= TEMP_MAX_C) then
FLastPlutoSocTempC := s;
// RSSI быстро меняется с сигналом — без сглаживания; обновляем, только если валиден.
if r > TELEMETRY_NONE then FLastPlutoRSSIdB := r;