using Common.Attributes; using DeviceCommand.Base; using Model.Models; using System; using System.Threading; using System.Threading.Tasks; namespace DeviceCommand.Devices { /// /// 环境箱(型号:RLT1000) 一拖三,支持温度/湿度/水温/水流量的监测与定值控制 (Modbus TCP 协议) /// [ACPCommand] public class RLT1000 : ModbusTcp { /// /// 构造函数:传入 初始化环境箱 Modbus TCP 通信参数 /// public RLT1000(TcpConfig config) : base(config) { } // Modbus 从站号 private const byte SlaveId = 1; #region 读取 /// /// 读取环境箱运行状态监控字 (保持寄存器 5) /// /// 取消令牌 /// 状态监控字 (ushort 原始值) public async Task 读取状态监控(CancellationToken ct = default) { ushort[] re = await ReadHoldingRegistersAsync(SlaveId, 5, 1, ct); return re[0]; } /// /// 读取环境箱当前温度值 (保持寄存器 10-11) /// /// 取消令牌 /// 当前温度值 (单位: ℃,保留两位小数) public async Task 读取当前温度(CancellationToken ct = default) { try { ushort[] re = await ReadHoldingRegistersAsync(SlaveId, 10, 2, ct); return Math.Round(ConvertToFloat(re), 2); } catch (Exception) { return 0; } } /// /// 读取环境箱当前湿度值 (保持寄存器 16-17) /// /// 取消令牌 /// 当前湿度值 (单位: %RH,保留两位小数) public async Task 读取当前湿度(CancellationToken ct = default) { ushort[] re = await ReadHoldingRegistersAsync(SlaveId, 16, 2, ct); return Math.Round(ConvertToFloat(re), 2); } /// /// 读取环境箱当前水温值 (保持寄存器 22-23) /// /// 取消令牌 /// 当前水温值 (单位: ℃,保留两位小数) public async Task 读取当前水温(CancellationToken ct = default) { try { ushort[] re = await ReadHoldingRegistersAsync(SlaveId, 22, 2, ct); return Math.Round(ConvertToFloat(re), 2); } catch (Exception) { return 0; } } /// /// 读取当前 1 号水流量值 (保持寄存器 28-29) /// /// 取消令牌 /// 1 号水流量值 (保留两位小数) public async Task 读取当前1号水流量值(CancellationToken ct = default) { ushort[] re = await ReadHoldingRegistersAsync(SlaveId, 28, 2, ct); return Math.Round(ConvertToFloat(re), 2); } /// /// 读取当前 2 号水流量值 (保持寄存器 34-35) /// /// 取消令牌 /// 2 号水流量值 (保留两位小数) public async Task 读取当前2号水流量值(CancellationToken ct = default) { ushort[] re = await ReadHoldingRegistersAsync(SlaveId, 34, 2, ct); return Math.Round(ConvertToFloat(re), 2); } /// /// 读取当前 3 号水流量值 (保持寄存器 40-41) /// /// 取消令牌 /// 3 号水流量值 (保留两位小数) public async Task 读取当前3号水流量值(CancellationToken ct = default) { ushort[] re = await ReadHoldingRegistersAsync(SlaveId, 40, 2, ct); return Math.Round(ConvertToFloat(re), 2); } #endregion #region 读写(控制命令) /// /// 切换环境箱为本地控制模式 (寄存器 147 写 0) /// /// 取消令牌 public async Task 切换为本地模式(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 147, 0, ct); } /// /// 切换环境箱为远程控制模式 (寄存器 147 写 1) /// /// 取消令牌 public async Task 切换为远程模式(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 147, 1, ct); } /// /// 远程模式下关闭环境箱 (寄存器 148 写 0) /// /// 取消令牌 public async Task 远程模式关机(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 148, 0, ct); } /// /// 远程模式下开启环境箱 (寄存器 148 写 1) /// /// 取消令牌 public async Task 远程模式开机(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 148, 1, ct); } /// /// 远程模式复位结束 (寄存器 149 写 0) /// /// 取消令牌 public async Task 远程模式复位结束(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 149, 0, ct); } /// /// 远程模式复位 (寄存器 149 写 1) /// /// 取消令牌 public async Task 远程模式复位(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 149, 1, ct); } /// /// 切换为程序运行模式 (寄存器 153 写 0) /// /// 取消令牌 public async Task 切换为程序模式(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 153, 0, ct); } /// /// 切换为定值运行模式 (寄存器 153 写 1) /// /// 取消令牌 public async Task 切换为定值模式(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 153, 1, ct); } /// /// 定值模式下设置目标温度 (寄存器 154-155) /// /// 目标温度值 (单位: ℃) /// 取消令牌 public async Task 定值温度设定(float 温度, CancellationToken ct = default) { var tmp = ConvertFromFloat(温度); await WriteMultipleRegistersAsync(SlaveId, 154, tmp, ct); } /// /// 定值模式下设置目标湿度 (寄存器 158-159) /// /// 目标湿度值 (单位: %RH) /// 取消令牌 public async Task 定值湿度设定(float 湿度, CancellationToken ct = default) { var tmp = ConvertFromFloat(湿度); await WriteMultipleRegistersAsync(SlaveId, 158, tmp, ct); } /// /// 定值模式下设置目标水温 (寄存器 162-163) /// /// 目标水温值 (单位: ℃) /// 取消令牌 public async Task 定值水温设定(float 水温, CancellationToken ct = default) { var tmp = ConvertFromFloat(水温); await WriteMultipleRegistersAsync(SlaveId, 162, tmp, ct); } /// /// 定值模式下设置 1 号水流量目标值 (寄存器 164-165) /// /// 1 号水流量目标值 /// 取消令牌 public async Task 定值1号水流量设定(float 水流量, CancellationToken ct = default) { var tmp = ConvertFromFloat(水流量); await WriteMultipleRegistersAsync(SlaveId, 164, tmp, ct); } /// /// 定值模式下设置 2 号水流量目标值 (寄存器 166-167) /// /// 2 号水流量目标值 /// 取消令牌 public async Task 定值2号水流量设定(float 水流量, CancellationToken ct = default) { var tmp = ConvertFromFloat(水流量); await WriteMultipleRegistersAsync(SlaveId, 166, tmp, ct); } /// /// 定值模式下设置 3 号水流量目标值 (寄存器 168-169) /// /// 3 号水流量目标值 /// 取消令牌 public async Task 定值3号水流量设定(float 水流量, CancellationToken ct = default) { var tmp = ConvertFromFloat(水流量); await WriteMultipleRegistersAsync(SlaveId, 168, tmp, ct); } /// /// 设置水温模式不使用 (寄存器 1181 写 0) /// /// 取消令牌 public async Task 水温模式不使用(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 1181, 0, ct); } /// /// 设置水温模式使用 (寄存器 1181 写 1) /// /// 取消令牌 public async Task 水温模式使用(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 1181, 1, ct); } /// /// 设置环境箱温度模式不使用 (寄存器 1182 写 0) /// /// 取消令牌 public async Task 环境箱温度模式不使用(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 1182, 0, ct); } /// /// 设置环境箱温度模式使用 (寄存器 1182 写 1) /// /// 取消令牌 public async Task 环境箱温度模式使用(CancellationToken ct = default) { await WriteSingleRegisterAsync(SlaveId, 1182, 1, ct); } #endregion #region 数据转换助手方法 /// /// 将两个 16 位寄存器(大端序)转换为 IEEE754 单精度浮点数 /// /// 两个 ushort 寄存器值 /// 转换后的浮点数值 private float ConvertToFloat(ushort[] values) { if (values == null || values.Length < 2) return 0f; 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); } /// /// 将单精度浮点数转换为两个 16 位寄存器(大端序) /// /// 待转换的浮点数值 /// 两个 ushort 寄存器值 private ushort[] ConvertFromFloat(float value) { byte[] bytes = BitConverter.GetBytes(value); ushort[] result = new ushort[2]; result[0] = (ushort)((bytes[3] << 8) | bytes[2]); result[1] = (ushort)((bytes[1] << 8) | bytes[0]); return result; } #endregion } }