BOB/DeviceCommand/Device/WS-68030-380T.cs

170 lines
5.0 KiB
C#

using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace DeviceCommand.Device
{
[BOBCommand]
public class WS_68030_380T : ModbusTcp
{
public WS_68030_380T(string IpAddress, int port, int SendTimeout, int ReceiveTimeout)
{
ConfigureDevice(IpAddress, 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 WriteSingleRegisterAsync(1,0,1);
}
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
private const byte SlaveAddress = 1;
public virtual async Task _KW(float , CancellationToken ct = default)
{
var send = ConvertFromFloat();
await WriteMultipleRegistersAsync(1, 58, send).WaitAsync(ct);
}
public virtual async Task (CancellationToken ct = default)
{
var tmp = new ushort();
ushort send = (ushort)(tmp | (1 << 8));
await WriteSingleRegisterAsync(1, 70, send).WaitAsync(ct);
}
public virtual async Task (CancellationToken ct = default)
{
await WriteSingleRegisterAsync(1, 70, new()).WaitAsync(ct);
}
public virtual async Task<float> _KW(CancellationToken ct = default)
{
var re = await ReadHoldingRegistersAsync(1, 58, 2).WaitAsync(ct);
return ConvertToFloat(re);
}
#region
protected float ConvertToFloat(ushort[] values)
{
byte[] bytes = new byte[4];
bytes[3] = (byte)(values[0] >> 8);
bytes[2] = (byte)(values[0] & 0xFF);
bytes[1] = (byte)(values[1] >> 8);
bytes[0] = (byte)(values[1] & 0xFF);
return BitConverter.ToSingle(bytes, 0);
}
protected ushort[] ConvertFromFloat(float value)
{
byte[] bytes = BitConverter.GetBytes(value);
return new ushort[]
{
(ushort)((bytes[3] << 8) | bytes[2]),
(ushort)((bytes[1] << 8) | bytes[0])
};
}
#endregion
}
}