257 lines
10 KiB
C#
257 lines
10 KiB
C#
using Common.Attributes;
|
||
using DeviceCommand.Base;
|
||
using Logger;
|
||
using System.Globalization;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace DeviceCommand.Device
|
||
{
|
||
[BOBCommand]
|
||
public class SQ0030G1D : Tcp
|
||
{
|
||
public SQ0030G1D(string ip, int port, int sendTimeout, int receiveTimeout)
|
||
{
|
||
ConfigureDevice(ip, port, sendTimeout, receiveTimeout);
|
||
}
|
||
#region 心跳
|
||
private CancellationTokenSource _cancellationTokenSource;
|
||
private Task? _heartbeatTask;
|
||
private const int HeartbeatInterval = 3000;
|
||
public bool IsActive = false;
|
||
public int ReConnectionAttempts = 0;
|
||
public const int MaxReconnectAttempts = 10;
|
||
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
|
||
{
|
||
await _commLock.WaitAsync(ct);
|
||
try
|
||
{
|
||
if (TcpClient != null && !TcpClient.Connected) TcpClient = new();
|
||
if (TcpClient.Connected)
|
||
{
|
||
return true;
|
||
}
|
||
await TcpClient.ConnectAsync(IPAddress, Port, ct);
|
||
IsActive = true;
|
||
StartHeartbeat();
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return false;
|
||
}
|
||
finally
|
||
{
|
||
_commLock.Release();
|
||
}
|
||
}
|
||
public override void Close()
|
||
{
|
||
if (!TcpClient.Connected)
|
||
{
|
||
throw new InvalidOperationException("TCP 没有连接成功");
|
||
}
|
||
if (TcpClient.Connected)
|
||
{
|
||
TcpClient.Close();
|
||
StopHeartbeat();
|
||
}
|
||
}
|
||
// 启动设备的心跳
|
||
public void StartHeartbeat()
|
||
{
|
||
if (_heartbeatTask != null)
|
||
return;
|
||
if (_cancellationTokenSource == null || _cancellationTokenSource.IsCancellationRequested)
|
||
_cancellationTokenSource = new();
|
||
_heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
|
||
}
|
||
|
||
// 停止设备的心跳
|
||
public void StopHeartbeat()
|
||
{
|
||
IsActive = false;
|
||
_cancellationTokenSource.Cancel();
|
||
_heartbeatTask = null;
|
||
}
|
||
|
||
private async Task HeartbeatLoop(CancellationToken ct)
|
||
{
|
||
while (!ct.IsCancellationRequested)
|
||
{
|
||
await Task.Delay(HeartbeatInterval, ct);
|
||
|
||
try
|
||
{
|
||
await 设置远程控制();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
IsActive = false;
|
||
ReConnectionAttempts++;
|
||
if (MaxReconnectAttempts < ReConnectionAttempts)
|
||
{
|
||
StopHeartbeat();
|
||
return;
|
||
}
|
||
await ReconnectDevice(ct);
|
||
}
|
||
}
|
||
}
|
||
private async Task ReconnectDevice(CancellationToken ct)
|
||
{
|
||
try
|
||
{
|
||
bool resultConnect = await ConnectAsync(ct);
|
||
if (resultConnect)
|
||
{
|
||
ReConnectionAttempts = 0;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
// ===================== 基础封装 =====================
|
||
|
||
protected virtual Task 写命令(string cmd, CancellationToken ct = default)
|
||
=> SendAsync(cmd + "\n", ct);
|
||
|
||
protected virtual async Task<string> 查询命令(string cmd, CancellationToken ct = default)
|
||
{
|
||
await SendAsync(cmd + "\n", ct);
|
||
return await ReadAsync(ct: ct);
|
||
}
|
||
|
||
// ===================== 1. 基础控制 =====================
|
||
|
||
public async Task 启动电源()
|
||
{
|
||
await 写命令($"OUTPut 1\n");
|
||
}
|
||
|
||
public async Task 关闭电源()
|
||
{
|
||
await 写命令($"OUTPut 0\n");
|
||
}
|
||
|
||
public virtual Task<string> 获取设备ID(CancellationToken ct = default)
|
||
=> 查询命令("*IDN?", ct);
|
||
|
||
public virtual Task 重置设备(CancellationToken ct = default)
|
||
=> 写命令("*RST", ct);
|
||
|
||
public virtual Task 设置远程控制(CancellationToken ct = default)
|
||
=> 写命令("SYST:REM", ct);
|
||
|
||
public virtual Task 设置本地控制(CancellationToken ct = default)
|
||
=> 写命令("SYST:LOC", ct);
|
||
|
||
public virtual Task 设置输出状态(bool on, CancellationToken ct = default)
|
||
=> 写命令($"OUTP:STAT {(on ? "ON" : "OFF")}", ct);
|
||
|
||
public virtual async Task<bool> 获取输出状态(CancellationToken ct = default)
|
||
=> (await 查询命令("OUTP:STAT?", ct)).Trim().ToUpper() == "ON";
|
||
|
||
// ===================== 2. 电压/频率控制 =====================
|
||
|
||
public virtual Task 设置输出电压(double value, CancellationToken ct = default)
|
||
=> 写命令($"VOLT {value}", ct);
|
||
|
||
public virtual async Task<double> 获取输出电压(CancellationToken ct = default)
|
||
=> double.Parse((await 查询命令("VOLT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture);
|
||
|
||
public virtual async Task<double> 获取输出频率(CancellationToken ct = default)
|
||
=> double.Parse((await 查询命令("FREQ?", ct)).Replace("Hz", ""), CultureInfo.InvariantCulture);
|
||
|
||
// ===================== 3. 保护 =====================
|
||
|
||
public virtual Task 设置过压保护(double v, CancellationToken ct = default)
|
||
=> 写命令($"VOLT:PROT {v}", ct);
|
||
|
||
public virtual async Task<double> 获取过压保护(CancellationToken ct = default)
|
||
=> double.Parse((await 查询命令("VOLT:PROT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture);
|
||
|
||
public virtual Task 设置过流保护(double a, CancellationToken ct = default)
|
||
=> 写命令($"CURR:PROT {a}", ct);
|
||
|
||
public virtual async Task<double> 获取过流保护(CancellationToken ct = default)
|
||
=> double.Parse((await 查询命令("CURR:PROT?", ct)).Replace("A", ""), CultureInfo.InvariantCulture);
|
||
|
||
public virtual Task 清除保护(CancellationToken ct = default)
|
||
=> 写命令("SYST:PROT:CLE", ct);
|
||
|
||
// ===================== 4. 测量 =====================
|
||
|
||
public virtual async Task<double> 测量输出电压(CancellationToken ct = default)
|
||
=> double.Parse((await 查询命令("MEAS:VOLT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture);
|
||
|
||
public virtual async Task<double> 测量输出电流(CancellationToken ct = default)
|
||
=> double.Parse((await 查询命令("MEAS:CURR?", ct)).Replace("A", ""), CultureInfo.InvariantCulture);
|
||
|
||
public virtual async Task<double> 测量输出功率(CancellationToken ct = default)
|
||
=> double.Parse((await 查询命令("MEAS:POW?", ct)).Replace("W", ""), CultureInfo.InvariantCulture);
|
||
|
||
public virtual async Task<(double volt, double curr, double pow)> 测量所有参数(CancellationToken ct = default)
|
||
{
|
||
var parts = (await 查询命令("MEAS:ARR?", ct)).Split(',');
|
||
return (
|
||
double.Parse(parts[0].Replace("V", ""), CultureInfo.InvariantCulture),
|
||
double.Parse(parts[1].Replace("A", ""), CultureInfo.InvariantCulture),
|
||
double.Parse(parts[2].Replace("W", ""), CultureInfo.InvariantCulture)
|
||
);
|
||
}
|
||
|
||
// 切换到远程控制模式
|
||
public virtual Task 设置远程控制模式(CancellationToken ct = default)
|
||
=> 写命令("SYST:REM", ct);
|
||
|
||
// 切换到本地控制模式
|
||
public virtual Task 设置本地控制模式(CancellationToken ct = default)
|
||
=> 写命令("SYST:LOC", ct);
|
||
|
||
// 设定三相电压高低档
|
||
public virtual Task 设置三相电压高低档(int range, CancellationToken ct = default)
|
||
=> 写命令($"OUTP:RANG {range}", ct); // 设定高低档:166(低档)/333(高档)
|
||
|
||
// 设定通用输出电压
|
||
public virtual Task 设置通用输出电压(double value, CancellationToken ct = default)
|
||
=> 写命令($"VOLT {value}", ct);
|
||
|
||
// 设定三相输出电压
|
||
public virtual Task 设置三相输出电压(double U, double V, double W, CancellationToken ct = default)
|
||
=> 写命令($"VOLT:PHAS A, {U}, B, {V}, C, {W}", ct);
|
||
|
||
// 设定输出频率
|
||
public virtual Task 设置输出频率(double freq, CancellationToken ct = default)
|
||
=> 写命令($"FREQ {freq}", ct);
|
||
|
||
// 设定步阶输出电压
|
||
public virtual Task 设置步阶输出电压(double targetVoltage, double stepTime, CancellationToken ct = default)
|
||
=> 写命令($"TRIG:TRAN:VOLT:STEP {targetVoltage}, {stepTime}", ct);
|
||
|
||
// 设定步阶输出频率
|
||
public virtual Task 设置步阶输出频率(double targetFrequency, double stepTime, CancellationToken ct = default)
|
||
=> 写命令($"TRIG:TRAN:FREQ:STEP {targetFrequency}, {stepTime}", ct);
|
||
|
||
// 设定渐变输出电压
|
||
public virtual Task 设置渐变输出电压(double startVoltage, double endVoltage, double sweepTime, CancellationToken ct = default)
|
||
=> 写命令($"TRIG:TRAN:VOLT:SWEEP {startVoltage}, {endVoltage}, {sweepTime}", ct);
|
||
|
||
// 设定渐变输出频率
|
||
public virtual Task 设置渐变输出频率(double startFreq, double endFreq, double sweepTime, CancellationToken ct = default)
|
||
=> 写命令($"TRIG:TRAN:FREQ:SWEEP {startFreq}, {endFreq}, {sweepTime}", ct);
|
||
|
||
// 设定软件启动功能起始电压与额定电压
|
||
public virtual Task 设置软件启动功能起始电压与额定电压(double startVoltage, double ratedVoltage, CancellationToken ct = default)
|
||
=> 写命令($"PON:VOLT {startVoltage}, {ratedVoltage}", ct);
|
||
|
||
// 设定软件启动功能起始电压与起始频率
|
||
public virtual Task 设置软件启动功能起始电压与起始频率(double startVoltage, double startFrequency, CancellationToken ct = default)
|
||
=> 写命令($"PON:FREQ {startVoltage}, {startFrequency}", ct);
|
||
}
|
||
}
|