using System; using System.Collections.Generic; using System.Linq; using System.Text; using EasyModbus; namespace HH.WCS.Mobox3.DSZSH.device { /// /// modbus tcp 用第三方的包 /// public class ModbusHelper { // 内存,连接上的 Modbus 通讯对象 private static Dictionary _ipPort_ModbusClient = new Dictionary(); public ModbusHelper(string ip, int port = 502, byte slaveId = 1) { Init(ip, port, slaveId); } /// /// Modbus 启动初始化 /// public static void Init(string ip, int port = 502, byte slaveId = 1) { // 配置文件读取所有的 Modbus 进行初始化 try { if (ip == null || ip.Trim() == "") { // 读取配置信息失败 LogHelper.Info("Modbus:读取配置信息失败"); return; } var modbusClient = new ModbusClient(ip, port); _ipPort_ModbusClient.Add($"{ip}:{port}({slaveId})", modbusClient); Link(modbusClient); } catch (Exception ex) { LogHelper.InfoEx(ex); } } /// /// 重连所有 Modbus 设备 /// public static void Relink() { try { if (_ipPort_ModbusClient.Count == 0) { return; } foreach (var item in _ipPort_ModbusClient) { if (!item.Value.Connected) { Link(item.Value); } } } catch (Exception ex) { LogHelper.InfoEx(ex); } } /// /// 连接 Modbus 下位机(私有,内部调用) /// /// private static void Link(ModbusClient modbusClient) { try { modbusClient.Disconnect(); modbusClient.Connect(); if (modbusClient.Connected) { //连接上 } else { //没连上 } } catch (Exception ex) { LogHelper.InfoEx(ex); } } /// /// 读一个或多个线圈,返回一个bit真假数组 /// /// /// /// /// /// public static bool[] ReadCoils(int address, int qty, string ip, int port = 502) { bool[] res = new bool[0]; var client = GetModbusClient(ip, port); if (client != null && client.Connected) { try { res = client.ReadCoils(address, qty); if (res.Length != 0) { //读取成功 } else { //读取失败 } } catch (Exception ex) { LogHelper.InfoEx(ex); } } else { } return res; } /// /// 写入单个线圈 /// /// /// /// /// public static bool WriteSingleCoil(int address, bool value, string ip, int port = 502) { var res = false; var client = GetModbusClient(ip, port); if (client != null && client.Connected) { try { client.WriteSingleCoil(address, value); res = value == client.ReadCoils(address, 1)[0]; if (res) { //写入成功 } else { //写入失败 } } catch (Exception ex) { } } else { } return res; } /// /// 写入多个线圈 /// /// /// /// /// public static bool WriteMultipleCoils(int address, bool[] values, string ip, int port = 502) { var res = false; var client = GetModbusClient(ip, port); if (client != null && client.Connected) { try { client.WriteMultipleCoils(address, values); var dataRead = client.ReadCoils(address, values.Length); res = values.SequenceEqual(dataRead); if (res) { //写入成功 } else { //写入失败 } } catch (Exception ex) { } } else { } return res; } /// /// 批量读取或单独读取保持寄存器,返回的是32位int数组 /// /// 读取起始位 /// 读取的数量 /// IP地址 /// 端口号 /// public static int[] ReadHoldingRegisters(int address, int qty, string ip, int port = 502) { int[] res = new int[0]; var client = GetModbusClient(ip, port); if (client != null && client.Connected) { try { //一个寄存器是16位,返回2个int类型 res = client.ReadHoldingRegisters(address, qty); if (res.Length != 0) { //读取成功 } else { //读取失败 } } catch (Exception ex) { //如果请求数量超出保持寄存器的最大数据行数,会报错 LogHelper.Info($"发生了异常:{ex.Message},IP:{ip},Port:{port}", "Error"); } } else { LogHelper.Info($"未找到Modbus设备实例对象:IP:{ip},Port:{port}"); } return res; } /// /// 写入单个寄存器数据 /// /// /// /// /// public static bool WriteSingleRegister(int address, int value, string ip, int port = 502) { var res = false; var client = GetModbusClient(ip, port); if (client != null && client.Connected) { try { client.WriteSingleRegister(address, value); res = value == client.ReadHoldingRegisters(address, 1)[0]; if (res) { //写入成功 } else { //写入失败 } } catch (Exception ex) { } } else { } return res; } /// /// 写入多个寄存器数据 /// /// /// /// /// public static bool WriteMultipleRegisters(int address, int[] values, string ip, int port = 502) { var res = false; var client = GetModbusClient(ip, port); var log = string.Join(",", values.Select(x => x.ToString())); if (client != null && client.Connected) { try { client.WriteMultipleRegisters(address, values); var dataRead = client.ReadHoldingRegisters(address, values.Length); res = values.SequenceEqual(dataRead); if (res) { LogHelper.Info($"写入成功,IP:{ip},Port:{port},{log}"); } else { LogHelper.Info($"写入失败,IP:{ip},Port:{port},{log}"); } } catch (Exception ex) { LogHelper.Info($"发生了异常:{ex.Message},IP:{ip},Port:{port},{log}", "Error"); } } else { LogHelper.Info($"未配置的设备信息,IP:{ip},Port:{port},{log}"); } return res; } /// /// 读一个或多个离散输入,返回一个bit真假数组 /// /// /// /// /// /// public static bool[] ReadDiscreteInputs(int address, int qty, string ip, int port = 502) { bool[] res = new bool[0]; var client = GetModbusClient(ip, port); if (client != null && client.Connected) { try { res = client.ReadDiscreteInputs(address, qty); if (res.Length != 0) { //读取成功 } else { //读取失败 } } catch (Exception ex) { } } else { } return res; } /// /// 读一个或多个输入寄存器,返回一个int32位数组 /// /// /// /// /// /// public static int[] ReadInputRegisters(int address, int qty, string ip, int port = 502) { int[] res = new int[0]; var client = GetModbusClient(ip, port); if (client != null && client.Connected) { try { res = client.ReadInputRegisters(address, qty); if (res.Length != 0) { //读取成功 } else { //读取失败 } } catch (Exception ex) { } } else { } return res; } public static string ReadHoldingRegistersToString(int address, int qty, string ip, int port = 502) { var readArray = ReadHoldingRegisters(address, qty, ip, port); return RegistersToString(readArray); } #region Modbus 协议读写字符串 // 将字符串转换为 Modbus 寄存器数组(int[] 形式,每个int存一个16位值) private static int[] StringToRegisters(string text) { // 填充为偶数长度 if (text.Length % 2 != 0) { text += '\0'; } byte[] bytes = Encoding.ASCII.GetBytes(text); int[] registers = new int[bytes.Length / 2]; for (int i = 0; i < registers.Length; i++) { // 大端序:高位字节在前 registers[i] = (bytes[i * 2] << 8) | bytes[i * 2 + 1]; } return registers; } // 将 Modbus 寄存器数组(int[])转换为字符串 private static string RegistersToString(int[] registers) { byte[] bytes = new byte[registers.Length * 2]; for (int i = 0; i < registers.Length; i++) { // 提取低16位(忽略高16位) ushort registerValue = (ushort)(registers[i] & 0xFFFF); // 解析大端序 bytes[i * 2] = (byte)(registerValue >> 8); // 高位字节 bytes[i * 2 + 1] = (byte)(registerValue & 0xFF); // 低位字节 } // 去除填充的空字符 string result = Encoding.ASCII.GetString(bytes).TrimEnd('\0'); return result; } #endregion /// /// 获取 Modbus 通讯对象(私有,内部调用) /// /// /// /// /// private static ModbusClient GetModbusClient(string ip, int port = 502, byte slaveId = 1) { if (_ipPort_ModbusClient.TryGetValue($"{ip}:{port}({slaveId})", out var modbusClient)) { return modbusClient; } return null; //if (_ipPort_ModbusClient.ContainsKey($"{ip}:{port}({slaveId})")) { // return _ipPort_ModbusClient[$"{ip}:{port}({slaveId})"]; //} //else { // return null; //} } } }