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<string, ModbusClient> clients = new Dictionary<string, ModbusClient>();
|
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;
|
}
|
/// <summary>
|
/// 读保持寄存器
|
/// </summary>
|
/// <param name="address"></param>
|
/// <param name="qty"></param>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
/// <returns></returns>
|
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);
|
}
|
/// <summary>
|
/// 读保持寄存器
|
/// </summary>
|
/// <param name="address"></param>
|
/// <param name="qty"></param>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
/// <returns></returns>
|
internal static bool[] ReadInputRegistersRtu2(int address, int qty, string ip, int port = 502)
|
{
|
//01 02 00 01 00 01 E8 0A
|
List<bool> res = new List<bool>();
|
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<bool> res = new List<bool>();
|
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();
|
}
|
|
/// <summary>
|
/// 写单个寄存器
|
/// </summary>
|
/// <param name="address"></param>
|
/// <param name="value"></param>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
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
|
}
|
}
|