BOB/DeviceCommand/Device/ZXKS.cs

122 lines
3.5 KiB
C#

using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DeviceCommand.Device
{
[BOBCommand]
public class ZXKS:ModbusTcp
{
public ZXKS(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
}
}