From bcc94b40fe5a9da7ccb038ea7c77443fed015216 Mon Sep 17 00:00:00 2001 From: Iwwww Date: Sun, 28 Dec 2025 23:07:07 +0300 Subject: [PATCH] =?UTF-8?q?feat(frontend):=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=87=D0=B0=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D1=82=D1=8B=20=D0=BD=D0=B8=D0=B6=D0=B5=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liveStream/model/liveStream.store.ts | 16 +++++++++------- .../src/pages/dashboard/ui/DashboardPage.tsx | 4 ++-- .../src/widgets/audioLive/ui/AudioLiveWidget.tsx | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/services/frontend/src/features/liveStream/model/liveStream.store.ts b/services/frontend/src/features/liveStream/model/liveStream.store.ts index 108f1b3..48e1285 100644 --- a/services/frontend/src/features/liveStream/model/liveStream.store.ts +++ b/services/frontend/src/features/liveStream/model/liveStream.store.ts @@ -11,7 +11,7 @@ type LiveStreamState = { lastMessageAt: number | null; // WS frequency control - requestedHz: number; // 1..60 + requestedHz: number; // 0.1-60 setRequestedHz: (hz: number) => void; // Window selection @@ -33,14 +33,14 @@ const PEAK_WINDOW_MS = 3_000; const WINDOW_OPTIONS_MS = [15_000, 30_000, 60_000, 120_000, 300_000] as const; const DEFAULT_WINDOW_MS = 60_000; -const MIN_HZ = 1; +const MIN_HZ = 0.1; const MAX_HZ = 60; const DEFAULT_REQUESTED_HZ = 10; // If there are more than 600 points in selected window -> downsample const MAX_CHART_POINTS = 600; -// UI updates not more than ~12 Hz (10–15 Hz recommended) +// UI updates not more than ~12 Hz const UI_FLUSH_HZ = 12; const UI_FLUSH_MS = Math.round(1000 / UI_FLUSH_HZ); @@ -58,10 +58,12 @@ let lastSeenSample: AudioSample | null = null; function clampInt(v: number, min: number, max: number): number { if (!Number.isFinite(v)) return min; - return Math.max(min, Math.min(max, Math.trunc(v))); + return Math.max(min, v); } -function isAllowedWindowMs(ms: number): ms is (typeof WINDOW_OPTIONS_MS)[number] { +function isAllowedWindowMs( + ms: number, +): ms is (typeof WINDOW_OPTIONS_MS)[number] { return (WINDOW_OPTIONS_MS as readonly number[]).includes(ms); } @@ -81,7 +83,8 @@ function buildWsUrl(base: string, hz: number): string { function trimPeakWindow(nowSampleMs: number): void { const cutoff = nowSampleMs - PEAK_WINDOW_MS; - while (peakWindow.length && peakWindow[0]!.timeMs < cutoff) peakWindow.shift(); + while (peakWindow.length && peakWindow[0]!.timeMs < cutoff) + peakWindow.shift(); // Safety cap: even at 60 Hz, 3 sec ~ 180 points; allow some jitter if (peakWindow.length > 512) peakWindow = peakWindow.slice(-512); @@ -255,4 +258,3 @@ export const useLiveStreamStore = create()((set, get) => { }, }; }); - diff --git a/services/frontend/src/pages/dashboard/ui/DashboardPage.tsx b/services/frontend/src/pages/dashboard/ui/DashboardPage.tsx index ec881f3..893aa97 100644 --- a/services/frontend/src/pages/dashboard/ui/DashboardPage.tsx +++ b/services/frontend/src/pages/dashboard/ui/DashboardPage.tsx @@ -7,9 +7,9 @@ export function DashboardPage() { return (
-

STM32 Audio Dashboard

+

STM32 Audio Analyze Dashboard

- WebSocket 10 Hz: rms_db [-50..0], freq_hz [20..8000] + Частоты: 129 Гц - 5,5 кГц; Громкость: -50 - 0 дБ

diff --git a/services/frontend/src/widgets/audioLive/ui/AudioLiveWidget.tsx b/services/frontend/src/widgets/audioLive/ui/AudioLiveWidget.tsx index ad3234c..f97be16 100644 --- a/services/frontend/src/widgets/audioLive/ui/AudioLiveWidget.tsx +++ b/services/frontend/src/widgets/audioLive/ui/AudioLiveWidget.tsx @@ -13,7 +13,7 @@ import { import { freqToNote } from "../../../entities/audioSample/lib/note"; import { formatTimeHHMMSS, isStale } from "../../../shared/lib/time"; -const HZ_OPTIONS = [1, 5, 10, 15, 30, 60] as const; +const HZ_OPTIONS: number[] = [0.1, 0.25, 0.5, 1, 2.5, 5, 10, 15] as const; const WINDOW_OPTIONS: Array<{ label: string; ms: number }> = [ { label: "15s", ms: 15_000 },