using EasyModbus; using HH.WCS.JiaTong.process; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace HH.WCS.JiaTong.device { internal class PlcHelper { private static Dictionary clients = new Dictionary(); private ModbusClient GetClient(string ip, int port) { ModbusClient client = null; LogHelper.Info($"GetClient:ip:{ip},port:{port}", "ModBus"); if (!clients.ContainsKey(ip)) { LogHelper.Info($"GetClient:ip:{ip},port:{port}.链接不存在,开始链接", "ModBus"); client = new ModbusClient(ip, port); try { client.Connect(); clients[ip] = client; LogHelper.Info($"GetClient:ip:{ip},port:{port}.链接成功", "ModBus"); } catch (Exception ex) { LogHelper.Info($"GetClient:ip:{ip},port:{port}.链接异常:{ex.Message}", "ModBus"); LogHelper.Error(ex.Message, ex); } } return client; } /// /// 读保持寄存器 /// /// /// /// /// /// internal int[] ReadHoldingRegisters(int address, int qty, string ip, int port = 502) { int[] res = new int[0]; // lock (ReadHoldingRegistersLock) // { LogHelper.Info($"ReadHoldingRegisters:SendMsg:Addr:{address},Qty:{qty},Ip:{ip},Port:{port}", "ModBus"); var client = GetClient(ip, port); if (client != null && client.Connected) { client.ConnectionTimeout = 5000; try { res = client.ReadHoldingRegisters(address, qty); client.Disconnect(); } catch (Exception ex) { //LogHelper.Error(ex.Message, ex); LogHelper.Info($"ReadHoldingRegisters:Error:{ex.Message}"); } // } LogHelper.Info($"ReadHoldingRegisters:ReqMsg:{JsonConvert.SerializeObject(res)},Addr:{address},Ip:{ip},Port:{port}", "ModBus"); } return res; } internal static void Receive(string ip, string msg) { //处理设备信号 DeviceProcess.Analysis(msg, ip); } internal static bool SendHex(string ip, string msg) { return TcpServer.TcpServerSend(ip, Hex2Bytes(msg)); } internal static void SendAscii(string ip, string msg) { TcpServer.TcpServerSend(ip, Encoding.ASCII.GetBytes(msg)); } internal static byte[] Hex2Bytes(string hexString) { hexString = hexString.Replace(" ", ""); if ((hexString.Length % 2) != 0) hexString += " "; byte[] returnBytes = new byte[hexString.Length / 2]; for (int i = 0; i < returnBytes.Length; i++) returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); return returnBytes; } internal static string Hex2Ascii(string hexString) { hexString = hexString.Replace(" ", ""); if ((hexString.Length % 2) != 0) hexString += " "; byte[] returnBytes = new byte[hexString.Length / 2]; for (int i = 0; i < returnBytes.Length; i++) returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); return Encoding.ASCII.GetString(returnBytes); } /// /// 读保持寄存器 /// /// /// /// /// /// internal static bool[] ReadInputRegistersRtu2(int address, int qty, string ip, int port = 502) { //01 02 00 01 00 01 E8 0A List res = new List(); var hex = $"0102{address.ToString("X4")}{qty.ToString("X4")}"; hex = hex + BitConverter.ToString(PlcHelper.CRC16LH(PlcHelper.Hex2Bytes(hex))).Replace("-", "").Replace(" ", ""); LogHelper.Info($"电梯状态判断:{hex} ip:{ip},port{port} ", "电梯"); var data = SendHexOnce(ip, port, hex); if (!string.IsNullOrEmpty(data)) { string fh = data.Substring(6, 2); var xhw = Convert.ToString(Convert.ToInt32(fh, 16), 2); if (xhw.Length == 3) { xhw = '0' + xhw; } else if (xhw.Length == 2) { xhw = '0' + '0' + xhw; } else if (xhw.Length == 1) { xhw = '0' + '0' + '0' + xhw; } foreach (var item in xhw) { if (true) { if (item == '1') { res.Add(true); } else { res.Add(false); } } } } return res.ToArray(); } internal static bool[] ReadInputRegistersRtu1(int address, int qty, string ip, int port = 502) { //01 02 00 01 00 01 E8 0A List res = new List(); var hex = $"0102{address.ToString("X4")}{qty.ToString("X4")}"; hex = hex + BitConverter.ToString(PlcHelper.CRC16LH(PlcHelper.Hex2Bytes(hex))).Replace("-", "").Replace(" ", ""); LogHelper.Info($"电梯状态判断:{hex} ip:{ip},port{port} ", "电梯"); var data = SendHexOnce(ip, port, hex); if (!string.IsNullOrEmpty(data)) { string fh = data.Substring(6, 2); var xhw = Convert.ToString(Convert.ToInt32(fh, 16), 2); if (xhw.Length != 4) { if (xhw.Length == 3) { xhw = '0' + xhw; } else if (xhw.Length == 2) { xhw = '0' + '0' + xhw; } else if (xhw.Length == 1) { xhw = '0' + '0' + '0' + xhw; } } StringBuilder sb = new StringBuilder(); for (int i = xhw.Length - 1; i >= 0; i--) { sb.Append(xhw[i]); } foreach (var item in sb.ToString()) { if (true) { if (item == '1') { res.Add(true); } else { res.Add(false); } } } } return res.ToArray(); } /// /// 写单个寄存器 /// /// /// /// /// internal static bool WriteSingleRegisterRtuT(int address, int value, string ip, int port = 502) { //01 05 00 01 FF 00 DD FA var code = value == 1 ? "FF" : "00"; var res = false; var hex = $"0105{address.ToString("X4")}{code}00"; hex = hex + BitConverter.ToString(PlcHelper.CRC16LH(PlcHelper.Hex2Bytes(hex))).Replace("-", "").Replace(" ", ""); //hex = hex + BitConverter.ToString(PlcHelper.CRC16LH(PlcHelper.Hex2Bytes(hex))).Replace("-", "").Replace(" ", ""); var data = SendHexOnce(ip, port, hex); LogHelper.Info($"电梯请求:{hex} ip:{ip},port{port} ", "电梯"); if (!string.IsNullOrEmpty(data)) { if (data == hex) { res = true; } } return res; } private static string SendHexOnce(string ip, int port, string hex) { var res = string.Empty; Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); client.Connect(ip, port); client.ReceiveTimeout = 2000; if (client.Connected) { client.Send(PlcHelper.Hex2Bytes(hex)); byte[] buffer = new byte[1024]; try { var length = client.Receive(buffer, SocketFlags.None); byte[] data = new byte[length]; Array.Copy(buffer, data, length); res = BitConverter.ToString(data).Replace("-", ""); } catch (Exception ex) { LogHelper.Error(ex.Message, ex); } client.Disconnect(true); client.Dispose(); } client = null; return res; } #region 进制转换+CRC internal static bool CheckCRC(string hex) { var result = false; var data = hex.Replace(" ", ""); if (data.Length % 2 == 0) { var code1 = data.Substring(data.Length - 4, 4).ToLower(); var code2 = BitConverter.ToString(CRC16LH(Hex2Bytes(data.Substring(0, data.Length - 4)))).Replace("-", "").Replace(" ", "").ToLower(); result = code1 == code2; } return result; } internal static byte[] CRC16LH(byte[] pDataBytes) { ushort crc = 0xffff; ushort polynom = 0xA001; for (int i = 0; i < pDataBytes.Length; i++) { crc ^= pDataBytes[i]; for (int j = 0; j < 8; j++) { if ((crc & 0x01) == 0x01) { crc >>= 1; crc ^= polynom; } else { crc >>= 1; } } } byte[] result = BitConverter.GetBytes(crc); return result; } internal static byte[] CRC16HL(byte[] pDataBytes) { ushort crc = 0xffff; ushort polynom = 0xA001; for (int i = 0; i < pDataBytes.Length; i++) { crc ^= pDataBytes[i]; for (int j = 0; j < 8; j++) { if ((crc & 0x01) == 0x01) { crc >>= 1; crc ^= polynom; } else { crc >>= 1; } } } byte[] result = BitConverter.GetBytes(crc).Reverse().ToArray(); return result; } #endregion } }