using Common.Attributes; using DeviceCommand.Base; using Logger; using NModbus; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DeviceCommand.Device { [BOBCommand] public class IOBoard : ModbusTcp { public IOBoard(string Ip地址, int 端口, int 发送超时, int 接收超时) { ConfigureDevice(Ip地址, 端口, 发送超时, 接收超时); } #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 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); Modbus = new ModbusFactory().CreateMaster(TcpClient); 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 public async Task 写输出开关(byte 站号, ushort 开始地址, bool data) { await Modbus.WriteSingleCoilAsync(站号, 开始地址, data); } public async Task 批量写输出开关(byte 站号, ushort 开始地址, bool[] datas) { await Modbus.WriteMultipleCoilsAsync(站号, 开始地址, datas); } public async Task 读输出开关(byte 站号, ushort 开始地址) { await Modbus.ReadCoilsAsync(站号, 开始地址, 1); } public async Task 批量读输出开关(byte 站号, ushort 开始地址,ushort 数量) { return await Modbus.ReadCoilsAsync(站号, 开始地址, 数量); } } }