// state.ts - Peak Holder алгоритм с таймером interface AppState { maxPoints: number; signalHistory: number[]; lastBufferSize: number; // Peak Holder параметры peakValue: number; // Текущее удерживаемое пиковое значение currentValue: number; // Текущее реальное значение (без сглаживания) peakTimer: number | null; // Таймер для сброса пика peakHoldTime: number; // Время удержания пика в миллисекундах } export const state: AppState = { maxPoints: 1000, signalHistory: [], lastBufferSize: 0, peakValue: 0, currentValue: 0, peakTimer: null, peakHoldTime: 3000, // миллисекунды удержания пика }; /** * Основная функция peak holder * @param target - новое значение (0-63) * @returns значение для отображения (пик, если таймер активен) */ export function updatePeakHolder(target: number): number { // Обновляем текущее значение state.currentValue = target; // Если новое значение больше текущего пика if (target > state.peakValue) { // Устанавливаем новый пик state.peakValue = target; // Сбрасываем и перезапускаем таймер resetPeakTimer(); startPeakTimer(); } // Возвращаем текущий пик для отображения return state.peakValue; } /** * Запуск таймера сброса пика */ function startPeakTimer(): void { if (state.peakTimer !== null) { clearTimeout(state.peakTimer); } state.peakTimer = window.setTimeout(() => { resetPeak(); }, state.peakHoldTime); } /** * Сброс таймера пика */ function resetPeakTimer(): void { if (state.peakTimer !== null) { clearTimeout(state.peakTimer); state.peakTimer = null; } } /** * Сброс пикового значения до текущего уровня */ function resetPeak(): void { state.peakValue = state.currentValue; state.peakTimer = null; // Опционально: лог для отладки // console.log(`[PeakHolder] Reset to: ${state.peakValue}`); } /** * Принудительный сброс пика (например, при потере связи) */ export function forceResetPeak(): void { resetPeakTimer(); state.peakValue = 0; state.currentValue = 0; } /** * Обновление времени удержания пика * @param ms - время в миллисекундах */ export function setPeakHoldTime(ms: number): void { state.peakHoldTime = ms; } /** * Получение текущего состояния пика (для отладки) */ export function getPeakInfo(): { peak: number; current: number; timerActive: boolean } { return { peak: state.peakValue, current: state.currentValue, timerActive: state.peakTimer !== null, }; } // ===== ОСТАВЛЯЕМ СУЩЕСТВУЮЩИЕ ФУНКЦИИ БЕЗ ИЗМЕНЕНИЙ ===== export function addSignal(value: number): void { state.signalHistory.push(value); if (state.signalHistory.length > state.maxPoints) { state.signalHistory = state.signalHistory.slice(-state.maxPoints); } } export function addSignals(values: number[], bufferSize: number): void { if (!Array.isArray(values) || values.length === 0) return; const newBytes = bufferSize - state.lastBufferSize; if (newBytes > 0 && newBytes <= values.length) { const fresh = values.slice(-newBytes); const decoded = fresh.map(b => b & 0x3F); state.signalHistory.push(...decoded); } state.lastBufferSize = bufferSize; if (state.signalHistory.length > state.maxPoints) { state.signalHistory = state.signalHistory.slice(-state.maxPoints); } } export function resetBufferTracking(): void { state.lastBufferSize = 0; forceResetPeak(); // Также сбрасываем пик при потере связи }