using Common.Attributes; using DeviceCommand.Base; using Logger; using System; using System.IO.Ports; using System.Net; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading.Tasks; namespace DeviceCommand.Device { [BOBCommand] public class LQ7500_D : ModbusRtu { public LQ7500_D(string 串口, int 波特率, int 数据位, StopBits 停止位, Parity 校验位, int 读取超时, int 接收超时) { ConfigureDevice(串口, 波特率, 数据位, 停止位, 校验位, 读取超时, 接收超时); } #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) { try { if (SerialPort.IsOpen) SerialPort.Close(); SerialPort.PortName = PortName; SerialPort.BaudRate = BaudRate; SerialPort.DataBits = DataBits; SerialPort.StopBits = StopBits; SerialPort.Parity = Parity; SerialPort.ReadTimeout = ReadTimeout; SerialPort.WriteTimeout = WriteTimeout; if (SerialPort.IsOpen) return true; SerialPort.Open(); IsActive = true; StartHeartbeat(); return true; } finally { } } public override void Close() { StopHeartbeat(); if (SerialPort.IsOpen) SerialPort.Close(); } public void StartHeartbeat() { if (_heartbeatTask != null && !_heartbeatTask.IsCompleted) return; _cancellationTokenSource?.Cancel(); _cancellationTokenSource?.Dispose(); _cancellationTokenSource = new CancellationTokenSource(); _heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token)); } public void StopHeartbeat() { try { IsActive = false; _cancellationTokenSource.Cancel(); _heartbeatTask = null; } catch { } _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 (ReConnectionAttempts > MaxReconnectAttempts) { LoggerHelper.InfoWithNotify("IT6724C重连多次失败"); StopHeartbeat(); return; } await ReconnectDevice(ct); } } } private async Task ReconnectDevice(CancellationToken ct) { try { bool ok = await ConnectAsync(ct); if (ok) ReConnectionAttempts = 0; } catch { } } #endregion public byte 从站地址 { get; set; } = 1; // 默认从站地址 private static readonly int[] Pow10Table = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; private async Task 确保连接() { if (SerialPort == null || !SerialPort.IsOpen) await ConnectAsync(); } #region 读取方法 public virtual async Task 读取温度分辨率() { await 确保连接(); return (await ReadHoldingRegistersAsync(从站地址, 35, 1))[0]; } public virtual async Task 读取内部传感器温度(ushort 分辨率 = 0) { await 确保连接(); if (分辨率 == 0) 分辨率 = await 读取温度分辨率(); var data = await ReadHoldingRegistersAsync(从站地址, 0, 1); return Math.Round(data[0] / (double)Pow10Table[分辨率], 分辨率 + 1); } public virtual async Task 读取外部传感器温度(ushort 分辨率 = 0) { await 确保连接(); if (分辨率 == 0) 分辨率 = await 读取温度分辨率(); var data = await ReadHoldingRegistersAsync(从站地址, 1, 1); return data[0] / (double)Pow10Table[分辨率]; } public virtual async Task 读取故障代码() { await 确保连接(); return (await ReadHoldingRegistersAsync(从站地址, 1, 1))[0]; } public virtual async Task 读取设备状态() { await 确保连接(); return (await ReadHoldingRegistersAsync(从站地址, 3, 1))[0]; } public virtual async Task 读取泵状态() { await 确保连接(); return (await ReadHoldingRegistersAsync(从站地址, 4, 1))[0]; } public virtual async Task 读取流量() { await 确保连接(); var data = await ReadHoldingRegistersAsync(从站地址, 17, 1); return Math.Round(data[0] / 10.0, 1); } #endregion #region 写入方法 public virtual async Task 写入流量设置(double 值) { await 确保连接(); short temp = (short)(值 * 10); ushort result = Unsafe.As(ref temp); await WriteSingleRegisterAsync(从站地址, 24, result); } public virtual async Task 写入设备状态(bool 开) { await 确保连接(); await WriteSingleRegisterAsync(从站地址, 3, (ushort)(开 ? 1 : 0)); } public virtual async Task 写入泵状态(bool 开) { await 确保连接(); await WriteSingleRegisterAsync(从站地址, 4, (ushort)(开 ? 1 : 0)); } public virtual async Task 设置温度(double 温度) { await 确保连接(); short temp = (short)(温度 * 100); ushort result = Unsafe.As(ref temp); await WriteSingleRegisterAsync(从站地址, 2, result); } public virtual async Task 设置温度上限(double 温度) { await 确保连接(); short temp = (short)(温度 * 100); ushort result = Unsafe.As(ref temp); await WriteSingleRegisterAsync(从站地址, 5, result); } public virtual async Task 设置温度下限(double 温度) { await 确保连接(); short temp = (short)(温度 * 100); ushort result = Unsafe.As(ref temp); await WriteSingleRegisterAsync(从站地址, 6, result); } public virtual async Task 设置软件超温(double 上限温度, double 下限温度) { await 确保连接(); short v1 = (short)(上限温度 * 100); short v2 = (short)(下限温度 * 100); ushort[] data = MemoryMarshal.Cast(new short[] { v1, v2 }).ToArray(); await WriteSingleRegisterAsync(从站地址, 30, data[0]); await Task.Delay(5); await WriteSingleRegisterAsync(从站地址, 31, data[1]); } public virtual async Task 设置硬件超温(double 上限温度) { await 确保连接(); short v1 = (short)(上限温度 * 100); ushort result = Unsafe.As(ref v1); await WriteSingleRegisterAsync(从站地址, 32, result); } #endregion } }