using Microsoft.Extensions.Options;
using SSPCTester.Devices.Config;
using SSPCTester.Devices.Interfaces;
using SSPCTester.Logic.Models;
namespace SSPCTester.Logic.Testing;
/// 功率损耗:采集输入/输出两端数据并计算损耗与效率。
public sealed class PowerTestLegacy : ITestModule
{
private readonly IDaq _daq;
private readonly DaqOptions _daqOptions;
public PowerTestLegacy(IDaq daq, IOptions options)
{
_daq = daq;
_daqOptions = options.Value.Daq;
}
public string Name => "功率损耗";
/// 每路采集次数。
public int SamplesPerChannel { get; set; } = 5;
/// 采样间隔(ms)。
public int IntervalMs { get; set; } = 100;
public async Task RunAsync(TestContext ctx, IProgress progress, CancellationToken ct)
{
// 输入端电压由高速采集卡读取,输出端电压/电流由 Modbus 继电器端读取。
int daqVoltageChannel = ResolveDaqVoltageChannel(_daqOptions);
if (!_daq.IsConnected) await _daq.ConnectAsync(ct).ConfigureAwait(false);
if (!ctx.Sspc.IsConnected) await ctx.Sspc.ConnectAsync(ct).ConfigureAwait(false);
int n = ctx.Sspc.ChannelCount;
ctx.Project.PowerResults.Clear();
for (int ch = 1; ch <= n; ch++)
{
ct.ThrowIfCancellationRequested();
var row = new PowerLossRow { Channel = ch, Status = TestStatus.Running };
ctx.Project.PowerResults.Add(row);
progress.Report(new TestProgress { ModuleName = Name, Step = ch - 1, TotalSteps = n, Message = $"采集 CH{ch} 输入/输出两端数据" });
try
{
double sumVin = 0, sumVout = 0, sumI = 0;
for (int s = 0; s < SamplesPerChannel; s++)
{
// 输出端:Modbus 继电器端电压 + 通流电流(SSPC 为串联开关,Iin = Iout)。
var measurement = await ctx.Sspc.ReadMeasurementAsync(ch, ct).ConfigureAwait(false);
// 输入端:高速采集卡电压。
var daqValues = await _daq.ReadInstantAsync(new[] { daqVoltageChannel }, ct).ConfigureAwait(false);
double vin = daqValues.Length > 0 ? daqValues[0] : double.NaN;
double vout = measurement.Voltage;
double current = Math.Abs(measurement.Current);
if (!double.IsFinite(vin) || !double.IsFinite(vout) || !double.IsFinite(current))
throw new InvalidOperationException("功率损耗采样无效:请检查采集卡电压通道标定与 Modbus 连接。");
sumVin += vin;
sumVout += vout;
sumI += current;
await Task.Delay(IntervalMs, ct).ConfigureAwait(false);
}
row.Vin = sumVin / SamplesPerChannel;
row.Vout = sumVout / SamplesPerChannel;
row.Iin = sumI / SamplesPerChannel;
row.Iout = sumI / SamplesPerChannel;
row.Status = TestStatus.Measured;
}
catch
{
row.Status = TestStatus.Fail;
throw;
}
progress.Report(new TestProgress { ModuleName = Name, Step = ch, TotalSteps = n, StepStatus = row.Status, Message = $"CH{ch} 损耗={row.PowerLossW:F2}W 效率={row.EfficiencyPct:F1}%" });
}
}
/// 解析用于输入端电压的高速采集卡通道(取已标定的电压通道,优先 OutputVoltage)。
internal static int ResolveDaqVoltageChannel(DaqOptions options)
{
if (options.Channels == null || options.Channels.Count == 0)
throw new InvalidOperationException("未配置采集卡通道,无法执行功率损耗测试。");
var candidates = options.Channels
.Where(x => x.PhysicalChannel >= 0 && x.PhysicalChannel < options.ChannelCount)
.Where(x => x.IsCalibrated)
.Where(x => IsVoltageRole(x.Role))
.ToArray();
var pick = candidates.FirstOrDefault(x => string.Equals(x.Role, nameof(DaqChannelRole.OutputVoltage), StringComparison.OrdinalIgnoreCase))
?? candidates.FirstOrDefault();
if (pick == null)
throw new InvalidOperationException("功率损耗测试需要一个已标定的采集卡电压通道(输入端电压),请在设置中配置并标定。");
return pick.PhysicalChannel;
}
private static bool IsVoltageRole(string? role) =>
Enum.TryParse(role, true, out var parsed)
&& parsed is DaqChannelRole.OutputVoltage or DaqChannelRole.InputVoltage;
}