import { autoResetRef, createInjectionState } from "@vueuse/core"; import { shallowRef, reactive, ref, computed } from "vue"; import { Mutex } from "async-mutex"; import { OscilloscopeFullConfig, OscilloscopeDataResponse, } from "@/APIClient"; import { AuthManager } from "@/utils/AuthManager"; import { useAlertStore } from "@/components/Alert"; import { useRequiredInjection } from "@/utils/Common"; export type OscilloscopeDataType = { x: number[]; y: number[] | number[][]; xUnit: "s" | "ms" | "us" | "ns"; yUnit: "V" | "mV" | "uV"; adFrequency: number; adVpp: number; adMax: number; adMin: number; }; // 默认配置 const DEFAULT_CONFIG: OscilloscopeFullConfig = new OscilloscopeFullConfig({ captureEnabled: false, triggerLevel: 128, triggerRisingEdge: true, horizontalShift: 0, decimationRate: 50, autoRefreshRAM: false, }); // 采样频率常量(后端返回) const [useProvideOscilloscope, useOscilloscopeState] = createInjectionState(() => { const oscData = shallowRef(); const alert = useRequiredInjection(useAlertStore); // 互斥锁 const operationMutex = new Mutex(); // 状态 const isApplying = ref(false); const isCapturing = ref(false); // 配置 const config = reactive(new OscilloscopeFullConfig({ ...DEFAULT_CONFIG })); // 采样点数(由后端数据决定) const sampleCount = ref(0); // 采样周期(ns),由adFrequency计算 const samplePeriodNs = computed(() => oscData.value?.adFrequency ? 1_000_000_000 / oscData.value.adFrequency : 200 ); // 应用配置 const applyConfiguration = async () => { if (operationMutex.isLocked()) { alert.warn("有其他操作正在进行中,请稍后再试", 3000); return; } const release = await operationMutex.acquire(); isApplying.value = true; try { const client = AuthManager.createAuthenticatedOscilloscopeApiClient(); const success = await client.initialize({ ...config }); if (success) { alert.success("示波器配置已应用", 2000); } else { throw new Error("应用失败"); } } catch (error) { alert.error("应用配置失败", 3000); } finally { isApplying.value = false; release(); } }; // 重置配置 const resetConfiguration = () => { Object.assign(config, { ...DEFAULT_CONFIG }); alert.info("配置已重置", 2000); }; const clearOscilloscopeData = () => { oscData.value = undefined; } // 获取数据 const getOscilloscopeData = async () => { try { const client = AuthManager.createAuthenticatedOscilloscopeApiClient(); const resp: OscilloscopeDataResponse = await client.getData(); // 解析波形数据 const binaryString = atob(resp.waveformData); const bytes = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); } sampleCount.value = bytes.length; // 构建时间轴 const x = Array.from( { length: bytes.length }, (_, i) => (i * samplePeriodNs.value) / 1000 // us ); const y = Array.from(bytes); oscData.value = { x, y, xUnit: "us", yUnit: "V", adFrequency: resp.adFrequency, adVpp: resp.adVpp, adMax: resp.adMax, adMin: resp.adMin, }; } catch (error) { alert.error("获取示波器数据失败", 3000); } }; // 定时器引用 let refreshIntervalId: number | undefined; // 刷新间隔(毫秒),可根据需要调整 const refreshIntervalMs = ref(1000); // 定时刷新函数 const startAutoRefresh = () => { if (refreshIntervalId !== undefined) return; refreshIntervalId = window.setInterval(async () => { await refreshRAM(); await getOscilloscopeData(); }, refreshIntervalMs.value); }; const stopAutoRefresh = () => { if (refreshIntervalId !== undefined) { clearInterval(refreshIntervalId); refreshIntervalId = undefined; isCapturing.value = false; } }; // 启动捕获 const startCapture = async () => { if (operationMutex.isLocked()) { alert.warn("有其他操作正在进行中,请稍后再试", 3000); return; } isCapturing.value = true; const release = await operationMutex.acquire(); try { const client = AuthManager.createAuthenticatedOscilloscopeApiClient(); const started = await client.startCapture(); if (!started) throw new Error("无法启动捕获"); alert.info("开始捕获...", 2000); // 启动定时刷新 startAutoRefresh(); } catch (error) { alert.error("捕获失败", 3000); isCapturing.value = false; stopAutoRefresh(); } finally { release(); } }; // 停止捕获 const stopCapture = async () => { if (!isCapturing.value) { alert.warn("当前没有正在进行的捕获操作", 2000); return; } isCapturing.value = false; stopAutoRefresh(); const release = await operationMutex.acquire(); try { const client = AuthManager.createAuthenticatedOscilloscopeApiClient(); const stopped = await client.stopCapture(); if (!stopped) throw new Error("无法停止捕获"); alert.info("捕获已停止", 2000); } catch (error) { alert.error("停止捕获失败", 3000); } finally { release(); } }; // 更新触发参数 const updateTrigger = async (level: number, risingEdge: boolean) => { const client = AuthManager.createAuthenticatedOscilloscopeApiClient(); try { const ok = await client.updateTrigger(level, risingEdge); if (ok) { config.triggerLevel = level; config.triggerRisingEdge = risingEdge; alert.success("触发参数已更新", 2000); } else { throw new Error(); } } catch { alert.error("更新触发参数失败", 2000); } }; // 更新采样参数 const updateSampling = async (horizontalShift: number, decimationRate: number) => { const client = AuthManager.createAuthenticatedOscilloscopeApiClient(); try { const ok = await client.updateSampling(horizontalShift, decimationRate); if (ok) { config.horizontalShift = horizontalShift; config.decimationRate = decimationRate; alert.success("采样参数已更新", 2000); } else { throw new Error(); } } catch { alert.error("更新采样参数失败", 2000); } }; // 手动刷新RAM const refreshRAM = async () => { const client = AuthManager.createAuthenticatedOscilloscopeApiClient(); try { const ok = await client.refreshRAM(); if (ok) { // alert.success("RAM已刷新", 2000); } else { throw new Error(); } } catch { alert.error("刷新RAM失败", 2000); } }; // 生成测试数据 const generateTestData = () => { const freq = 5_000_000; const duration = 0.001; // 1ms const points = Math.floor(freq * duration); const x = Array.from({ length: points }, (_, i) => (i * 1_000_000_000 / freq) / 1000); const y = Array.from({ length: points }, (_, i) => Math.floor(Math.sin(i * 0.01) * 127 + 128) ); oscData.value = { x, y, xUnit: "us", yUnit: "V", adFrequency: freq, adVpp: 2.0, adMax: 255, adMin: 0, }; alert.success("测试数据生成成功", 2000); }; const isOperationInProgress = computed( () => isApplying.value || isCapturing.value || operationMutex.isLocked() ); return { oscData, config, isApplying, isCapturing, isOperationInProgress, sampleCount, samplePeriodNs, refreshIntervalMs, applyConfiguration, resetConfiguration, clearOscilloscopeData, getOscilloscopeData, startCapture, stopCapture, updateTrigger, updateSampling, refreshRAM, generateTestData, }; }); export { useProvideOscilloscope, useOscilloscopeState, DEFAULT_CONFIG };