SSPC-Tester/SSPCTester.Devices/Drivers/ConfigurableDevices.cs
2026-06-30 12:10:29 +08:00

127 lines
7.6 KiB
C#

using Microsoft.Extensions.Options;
using SSPCTester.Devices.Config;
using SSPCTester.Devices.Drivers.Mock;
using SSPCTester.Devices.Drivers.Real;
using SSPCTester.Devices.Interfaces;
namespace SSPCTester.Devices.Drivers;
/// <summary>根据可变设置在 Mock 与真实 SSPC 间切换。</summary>
public sealed class ConfigurableSspc : ISspc
{
private readonly DeviceOptions _options;
private readonly MockSspc _mock;
private readonly SspcModbus _real;
public ConfigurableSspc(IOptions<DeviceOptions> options, MockSspc mock, SspcModbus real)
{
_options = options.Value;
_mock = mock;
_real = real;
_mock.ConnectionChanged += Forward;
_real.ConnectionChanged += Forward;
}
private ISspc Current => _options.Sspc.UseMock ? _mock : _real;
public int ChannelCount => 24;
public bool IsConnected => Current.IsConnected;
public string DisplayName => Current.DisplayName;
public event EventHandler<bool>? ConnectionChanged;
public Task<bool> ConnectAsync(CancellationToken ct = default) => Current.ConnectAsync(ct);
public async Task DisconnectAsync()
{
await _mock.DisconnectAsync().ConfigureAwait(false);
await _real.DisconnectAsync().ConfigureAwait(false);
}
public Task TurnOnAsync(int physicalSlot, CancellationToken ct = default) => Current.TurnOnAsync(physicalSlot, ct);
public Task TurnOffAsync(int physicalSlot, CancellationToken ct = default) => Current.TurnOffAsync(physicalSlot, ct);
public Task FlashAsync(int physicalSlot, int milliseconds, CancellationToken ct = default) => Current.FlashAsync(physicalSlot, milliseconds, ct);
public Task<bool> GetChannelStateAsync(int physicalSlot, CancellationToken ct = default) => Current.GetChannelStateAsync(physicalSlot, ct);
public Task<ChannelMeasurement> ReadMeasurementAsync(int physicalSlot, CancellationToken ct = default) => Current.ReadMeasurementAsync(physicalSlot, ct);
public Task<IReadOnlyList<ChannelMeasurement>> ReadMeasurementsAsync(CancellationToken ct = default) => Current.ReadMeasurementsAsync(ct);
private void Forward(object? sender, bool connected) => ConnectionChanged?.Invoke(this, connected);
}
public sealed class ConfigurablePowerSupply : IPowerSupply
{
private readonly DeviceOptions _options;
private readonly MockPowerSupply _mock;
private readonly Udp5080 _real;
public ConfigurablePowerSupply(IOptions<DeviceOptions> options, MockPowerSupply mock, Udp5080 real)
{
_options = options.Value; _mock = mock; _real = real;
_mock.ConnectionChanged += Forward; _real.ConnectionChanged += Forward;
}
private IPowerSupply Current => _options.PowerSupply.UseMock ? _mock : _real;
public bool IsConnected => Current.IsConnected;
public string DisplayName => Current.DisplayName;
public event EventHandler<bool>? ConnectionChanged;
public Task<bool> ConnectAsync(CancellationToken ct = default) => Current.ConnectAsync(ct);
public async Task DisconnectAsync() { await _mock.DisconnectAsync(); await SafeDisconnect(_real); }
public Task SetVoltageAsync(double volts, CancellationToken ct = default) => Current.SetVoltageAsync(volts, ct);
public Task SetCurrentLimitAsync(double amps, CancellationToken ct = default) => Current.SetCurrentLimitAsync(amps, ct);
public Task OutputAsync(bool on, CancellationToken ct = default) => Current.OutputAsync(on, ct);
public Task<(double volts, double amps)> ReadAsync(CancellationToken ct = default) => Current.ReadAsync(ct);
public Task<string> QueryIdentityAsync(CancellationToken ct = default) => Current.QueryIdentityAsync(ct);
private void Forward(object? sender, bool connected) => ConnectionChanged?.Invoke(this, connected);
private static async Task SafeDisconnect(IDeviceConnection device) { try { await device.DisconnectAsync(); } catch (NotImplementedException) { } }
}
public sealed class ConfigurableLoad : ILoad
{
private readonly DeviceOptions _options;
private readonly MockLoad _mock;
private readonly It87xxLoad _real;
public ConfigurableLoad(IOptions<DeviceOptions> options, MockLoad mock, It87xxLoad real)
{
_options = options.Value; _mock = mock; _real = real;
_mock.ConnectionChanged += Forward; _real.ConnectionChanged += Forward;
}
private ILoad Current => _options.Load.UseMock ? _mock : _real;
public bool IsConnected => Current.IsConnected;
public string DisplayName => Current.DisplayName;
public event EventHandler<bool>? ConnectionChanged;
public Task<bool> ConnectAsync(CancellationToken ct = default) => Current.ConnectAsync(ct);
public async Task DisconnectAsync() { await _mock.DisconnectAsync(); await SafeDisconnect(_real); }
public Task SetModeAsync(LoadMode mode, CancellationToken ct = default) => Current.SetModeAsync(mode, ct);
public Task SetValueAsync(double value, CancellationToken ct = default) => Current.SetValueAsync(value, ct);
public Task InputAsync(bool on, CancellationToken ct = default) => Current.InputAsync(on, ct);
public Task<(double volts, double amps)> ReadAsync(CancellationToken ct = default) => Current.ReadAsync(ct);
public Task<PowerReading> ReadPowerAsync(CancellationToken ct = default) => Current.ReadPowerAsync(ct);
public Task<string> QueryIdentityAsync(CancellationToken ct = default) => Current.QueryIdentityAsync(ct);
private void Forward(object? sender, bool connected) => ConnectionChanged?.Invoke(this, connected);
private static async Task SafeDisconnect(IDeviceConnection device) { try { await device.DisconnectAsync(); } catch (NotImplementedException) { } }
}
public sealed class ConfigurableDaq : IDaq
{
private readonly DeviceOptions _options;
private readonly MockDaq _mock;
private readonly Pcie8586Daq _real;
public ConfigurableDaq(IOptions<DeviceOptions> options, MockDaq mock, Pcie8586Daq real)
{
_options = options.Value; _mock = mock; _real = real;
_mock.ConnectionChanged += Forward; _real.ConnectionChanged += Forward;
_mock.SampleReceived += ForwardSample; _real.SampleReceived += ForwardSample;
}
private IDaq Current => _options.Daq.UseMock ? _mock : _real;
public bool IsConnected => Current.IsConnected;
public string DisplayName => Current.DisplayName;
public event EventHandler<bool>? ConnectionChanged;
public event EventHandler<CurveSample>? SampleReceived;
public Task<IReadOnlyList<DaqDeviceDescriptor>> EnumerateDevicesAsync(CancellationToken ct = default) =>
Current.EnumerateDevicesAsync(ct);
public Task<bool> ConnectAsync(CancellationToken ct = default) => Current.ConnectAsync(ct);
public async Task DisconnectAsync() { await _mock.DisconnectAsync(); await SafeDisconnect(_real); }
public Task<CurveData> CaptureAsync(int[] channels, int sampleRateHz, double durationSec, CancellationToken ct = default) =>
Current.CaptureAsync(channels, sampleRateHz, durationSec, ct);
public Task<double[]> ReadInstantAsync(int[] channels, CancellationToken ct = default) => Current.ReadInstantAsync(channels, ct);
public Task<CurveData> CaptureAroundActionAsync(
DaqActionCaptureRequest request,
Func<CancellationToken, Task> action,
CancellationToken ct = default) => Current.CaptureAroundActionAsync(request, action, ct);
private void Forward(object? sender, bool connected) => ConnectionChanged?.Invoke(this, connected);
private void ForwardSample(object? sender, CurveSample sample) => SampleReceived?.Invoke(this, sample);
private static async Task SafeDisconnect(IDeviceConnection device) { try { await device.DisconnectAsync(); } catch (NotImplementedException) { } }
}