封装实体类代码
using System.Net.NetworkInformation;
using System.Net.Sockets;
public abstract class PLCBase
{
/// <summary>
/// 互斥锁
/// </summary>
protected Mutex mutex = new Mutex();
public bool IsConnect { get; set; } = false;
/// <summary>
/// IP地址
/// </summary>
protected string IP { get; set; } = "127.0.0.1";
/// <summary>
/// 端口
/// </summary>
protected UInt16 Port { get; set; } = 502;
public enum EValueType { _BOOL, _INT16, _INT32, _INT64, _FLOAT, _DOUBLE, _STRING, _UINT16, _UINT32, _UINT64, _UNKNOW };
public Socket SocketClient
{
get
{
if (_socket == null)
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { SendTimeout = 300, ReceiveTimeout = 1000 };
return _socket;
}
if (_socket.Connected == false)
{
_socket.Close();
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { SendTimeout = 300, ReceiveTimeout = 1000 };
}
return _socket;
}
}
private Socket _socket;
//public static Socket SocketClient
//{
// get
// {
// --断开自动重新创建连接
// if (!_SocketClient.Connected)
// {
// _SocketClient.Close();
// _SocketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// _SocketClient.Connect(new IPEndPoint(IPAddress.Parse("IP地址"), _port)); //配置服务器IP与端口
// return _SocketClient;
// }
// return _SocketClient;
// }
//}
public bool Connect()
{
try
{
if (new System.Net.NetworkInformation.Ping().Send(IP, 1000).Status != IPStatus.Success)
return false;
if (!Connect(IP, Port))
return false;
IsConnect = true;
return true;
}
catch
{
IsConnect = false;
return false;
}
}
public bool Connect(string ip, UInt16 port)
{
try { IPAddress.Parse(ip); }
catch { return false; }
SocketClient.Connect(IPAddress.Parse(ip), port);
return SocketClient.Connected;
}
public void Connect(Socket socket, string host, int port, TimeSpan timeout)
{
AsyncConnect(socket, (s, a, o) => s.BeginConnect(host, port, a, o), timeout);
}
/// <summary>
/// Connects the specified socket.
/// </summary>
/// <param name="socket">The socket.</param>
/// <param name="addresses">The addresses.</param>
/// <param name="port">The port.</param>
/// <param name="timeout">The timeout.</param>
public void Connect(Socket socket, IPAddress addresses, int port, TimeSpan timeout)
{
AsyncConnect(socket, (s, a, o) => s.BeginConnect(addresses, port, a, o), timeout);
}
/// <summary>
/// Asyncs the connect.
/// </summary>
/// <param name="socket">The socket.</param>
/// <param name="connect">The connect.</param>
/// <param name="timeout">The timeout.</param>
private void AsyncConnect(Socket socket, Func<Socket, AsyncCallback, object, IAsyncResult> connect, TimeSpan timeout)
{
var asyncResult = connect(socket, null, null);
if (!asyncResult.AsyncWaitHandle.WaitOne(timeout))
{
try
{
socket.EndConnect(asyncResult);
}
catch (SocketException)
{ }
catch (ObjectDisposedException)
{ }
}
}
public void DisConnect()
{
IsConnect = false;
SocketClient.Disconnect(true);
}
public static byte[] FormatConversion(byte[] bytes)
{
for (int j = 0; j * 2 + 1 < bytes.Length; j++)
{
byte temp = bytes[2 * j];
bytes[2 * j] = bytes[2 * j + 1];
bytes[2 * j + 1] = temp;
}
return bytes;
}
}
using System.Net.Sockets;
public interface IPLCBase
{
Socket SocketClient { get; }
bool Connect();
void DisConnect();
List<bool> ReadBools(string addr, UInt16 count);
bool ReadBool(string addr);
Int16 ReadInt16(string addr);
List<Int16> ReadInt16s(string addr, UInt16 count);
List<byte> ReadAllByte(string addr, UInt16 count = 65535);
UInt16 ReadUInt16(string addr);
List<UInt16> ReadUInt16s(string addr, UInt16 count);
string ReadString(string addr, UInt16 count, bool stringFormate = true);
double ReadDouble(string addr);
List<double> ReadDoubles(string addr, UInt16 count);
Int32 ReadInt32(string addr);
List<Int32> ReadInt32s(string addr, UInt16 count);
UInt32 ReadUInt32(string addr);
List<UInt32> ReadUInt32s(string addr, UInt16 count);
UInt64 ReadUInt64(string addr);
List<UInt64> ReadUInt64s(string addr, UInt16 count);
Int64 ReadInt64(string addr);
List<Int64> ReadInt64s(string addr, UInt16 count);
float ReadFloat(string addr);
List<float> ReadFloats(string addr, UInt16 count);
bool WriteBool(string addr, bool value);
bool WriteBools(string addr, List<bool> value);
bool WriteInt16(string addr, Int16 value);
bool WriteInt16s(string addr, List<Int16> value);
bool WriteUInt16(string addr, UInt16 value);
bool WriteUInt16s(string addr, List<UInt16> value);
bool WriteInt32(string addr, Int32 value);
bool WriteInt32s(string addr, List<Int32> value);
bool WriteUInt32(string addr, UInt32 value);
bool WriteUInt32s(string addr, List<UInt32> value);
bool WriteInt64(string addr, Int64 value);
bool WriteInt64s(string addr, List<Int64> value);
bool WriteUInt64(string addr, UInt64 value);
bool WriteUInt64s(string addr, List<UInt64> value);
bool WriteDouble(string addr, double value);
bool WriteDoubles(string addr, List<double> value);
bool WriteFloat(string addr, float value);
bool WriteFloats(string addr, List<float> value);
bool WriteString(string addr, string value);
}
public class IPLC
{
private bool isConnect = false;
public bool IsConnect { get { return this.isConnect; } set { this.isConnect = value; } }
public string ErrorMsg { get; set; }
public IPLCBase _iPLC;
private IPLC()
{
//IsConnect = Connect();
}
public void DisConnect()
{
// _iPLC.DisConnect();
// this.IsConnect = false;
}
private static byte[] obj = new byte[0];
private static IPLC instance;
public static IPLC Instance
{
get
{
if (instance == null)
{
lock (obj)
{
if (instance == null)
{
instance = new IPLC();
}
}
}
return instance;
}
}
private static IPLC writer;
public static IPLC Writer
{
get
{
if (writer == null)
{
lock (obj)
{
if (writer == null)
{
writer = new IPLC();
}
}
}
return writer;
}
}
public bool Connect()
{
try
{
//_iPLC.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { SendTimeout = 300, ReceiveTimeout = 1000, };
IsConnect = _iPLC.Connect();
return IsConnect;
}
catch (Exception ex)
{
ErrorMsg = ex.Message;
IsConnect = false;
return IsConnect;
}
}
public string ReadValue(string addr, EValueType valueType)
{
// 不可读string
string result = string.Empty;
//if (!IsConnect) return (T)result;
switch (valueType)
{
case EValueType._BOOL:
{
result = Convert.ToInt16(ReadBool(addr)).ToString();
break;
}
case EValueType._INT16:
{
result = ReadInt16(addr).ToString();
break;
}
case EValueType._INT32:
{
result = ReadInt32(addr).ToString();
break;
}
case EValueType._INT64:
{
result = ReadInt64(addr).ToString();
break;
}
case EValueType._FLOAT:
{
result = ReadFloat(addr).ToString();
break;
}
case EValueType._DOUBLE:
{
result = ReadDouble(addr).ToString();
break;
}
default:
break;
}
return result;
}
public bool ReadBool(string addr)
{
if (!IsConnect) return false;
return _iPLC.ReadBool(addr);
}
public short ReadInt16(string addr)
{
if (!IsConnect) return (short)0;
return (short)_iPLC.ReadInt16(addr);
}
public int ReadInt32(string addr)
{
if (!IsConnect) return 0;
return _iPLC.ReadInt32(addr);
}
public long ReadInt64(string addr)
{
if (!IsConnect) return (long)0;
return _iPLC.ReadInt64(addr);
}
public float ReadFloat(string addr)
{
if (!IsConnect) return 0;
return _iPLC.ReadFloat(addr);
}
public double ReadDouble(string addr)
{
if (!IsConnect) return 0;
return _iPLC.ReadDouble(addr);
}
public List<bool> ReadBool(string addr, ushort length)
{
if (!IsConnect) return new List<bool>();
return _iPLC.ReadBools(addr, length);
}
public List<short> ReadInt16(string addr, ushort length)
{
if (!IsConnect) return new List<short>();
return _iPLC.ReadInt16s(addr, length);
}
public List<ushort> ReadUInt16(string addr, ushort length)
{
if (!IsConnect) return new List<ushort>();
return _iPLC.ReadUInt16s(addr, length);
}
public List<byte> ReadAllByte(string addr, ushort length)
{
if (!IsConnect) return new List<byte>();
return _iPLC.ReadAllByte(addr, length);
}
public List<int> ReadInt32(string addr, ushort length)
{
if (!IsConnect) return new List<int>();
return _iPLC.ReadInt32s(addr, length);
}
public List<uint> ReadUInt32(string addr, ushort length)
{
if (!IsConnect) return new List<uint>();
return _iPLC.ReadUInt32s(addr, length);
}
public List<long> ReadInt64(string addr, ushort length)
{
if (!IsConnect) return new List<long>();
return _iPLC.ReadInt64s(addr, length);
}
public List<ulong> ReadUInt64(string addr, ushort length)
{
if (!IsConnect) return new List<ulong>();
return _iPLC.ReadUInt64s(addr, length);
}
public List<float> ReadFloat(string addr, ushort length)
{
if (!IsConnect) return new List<float>();
return _iPLC.ReadFloats(addr, length);
}
public List<double> ReadDouble(string addr, ushort length)
{
if (!IsConnect)
return new List<double>();
return _iPLC.ReadDoubles(addr, length);
}
public string ReadString(string addr, ushort length)
{
if (!IsConnect) return "";
//string str = _iPLC.ReadString(addr, length);
//char[] chars = str.ToArray();
//for (int i = 0; 2 * i < chars.Length; i++)
//{
// char temp = chars[2 * i];
// chars[2 * i] = chars[2 * i + 1];
// chars[2 * i + 1] = temp;
//}
//return new string(chars);
return _iPLC.ReadString(addr, length);
}
public bool WriteBool(string addr, bool value)
{
// 江门调试阶段,屏蔽写操作
if (!IsConnect) return false;
return _iPLC.WriteBool(addr, value);
}
public bool WriteInt16(string addr, short value)
{
// 江门调试阶段,屏蔽写操作
if (!IsConnect) return false;
return _iPLC.WriteInt16(addr, value);
}
public bool WriteUInt16(string addr, ushort value)
{
// 江门调试阶段,屏蔽写操作
if (!IsConnect) return false;
return _iPLC.WriteUInt16(addr, value);
}
public bool WriteInt32(string addr, int value)
{
// 江门调试阶段,屏蔽写操作
if (!IsConnect) return false;
return _iPLC.WriteInt32(addr, value);
}
public bool WriteUInt32(string addr, uint value)
{
// 江门调试阶段,屏蔽写操作
if (!IsConnect) return false;
return _iPLC.WriteUInt32(addr, value);
}
public bool WriteInt64(string addr, long value)
{
if (!IsConnect) return false;
return _iPLC.WriteInt64(addr, value);
}
public bool WriteUInt64(string addr, ulong value)
{
if (!IsConnect) return false;
return _iPLC.WriteUInt64(addr, value);
}
public bool WriteFloat(string addr, float value)
{
if (!IsConnect) return false;
return _iPLC.WriteFloat(addr, value);
}
public bool WriteDouble(string addr, double value)
{
if (!IsConnect) return false;
return _iPLC.WriteDouble(addr, value);
}
public bool WriteString(string addr, string value)
{
if (!IsConnect) return false;
return _iPLC.WriteString(addr, value);
}
public bool WriteValue(string addr, EValueType valueType, string inputVal)
{
bool result = false;
if (!IsConnect) return result;
switch (valueType)
{
case EValueType._BOOL:
{
result = _iPLC.WriteBool(addr, Convert.ToBoolean(inputVal));
break;
}
case EValueType._INT16:
{
result = _iPLC.WriteInt16(addr, Convert.ToInt16(inputVal));
break;
}
case EValueType._INT32:
{
result = _iPLC.WriteInt32(addr, Convert.ToInt32(inputVal));
break;
}
case EValueType._INT64:
{
result = _iPLC.WriteInt64(addr, Convert.ToInt64(inputVal));
break;
}
case EValueType._FLOAT:
{
result = _iPLC.WriteFloat(addr, (float)Convert.ToDouble(inputVal));
break;
}
case EValueType._DOUBLE:
{
result = _iPLC.WriteDouble(addr, Convert.ToDouble(inputVal));
break;
}
case EValueType._STRING:
{
result = _iPLC.WriteString(addr, inputVal);
break;
}
default:
result = false;
break;
}
return result;
}
public List<T> ToList<T>(T[] input)
{
return input.ToList();
}
/// <summary>
/// 默认直接用数据库中的类型,如果是手动选择的,不要用
/// </summary>
/// <param name="valueTypeStr"></param>
/// <param name="address"></param>
/// <param name="value"></param>
/// <returns></returns>
public string GetValueByTypeString(string valueTypeStr, string address)
{
switch (valueTypeStr.ToUpper())
{
case "BOOL":
return Convert.ToInt16(this.ReadBool(address)).ToString();
case "INT_16":
case "INT":
case "SHORT":
case "WORD":
return this.ReadInt16(address).ToString();
case "DWORD":
case "DINT":
case "UINT":
return this.ReadInt32(address).ToString();
case "TIME":
case "REAL":
case "FLOAT":
return this.ReadFloat(address).ToString("0.00");
case "LREAL":
case "DOUBLE":
return this.ReadDouble(address).ToString("0.00");
default:
throw new IndexOutOfRangeException($"该类型的PLC地址{valueTypeStr.ToUpper()}尚未定义转换类型!");
}
}
public string GetBytesValueByTypeString(string valueTypeStr, byte[] values, int Lenth)
{
switch (valueTypeStr.ToUpper())
{
case "INT_16":
case "INT":
case "SHORT":
case "WORD":
values = values.Skip(Lenth * 2).Take(4).ToArray();
return BitConverter.ToInt32(ByteArrayFormat(values), 0).ToString();
case "DWORD":
case "DINT":
case "UINT":
values = values.Skip(Lenth * 2).Take(4).ToArray();
return BitConverter.ToUInt32(ByteArrayFormat(values), 0).ToString();
case "TIME":
case "REAL":
case "FLOAT":
//values = values.Skip(Lenth * 2).Take(4).ToArray();
return BitConverter.ToSingle(ByteArrayFormat(values.Skip(Lenth * 2).Take(4).ToArray()), 0).ToString();
case "LREAL":
case "DOUBLE":
//values = values.Skip(Lenth * 2).Take(4).ToArray();
return BitConverter.ToDouble(ByteArrayFormat(values.Skip(Lenth * 2).Take(8).ToArray()), 0).ToString();
default:
throw new IndexOutOfRangeException($"该类型的PLC地址{valueTypeStr.ToUpper()}尚未定义转换类型!");
}
}
private byte[] ByteArrayFormat(byte[] array)
{
for (int i = 0; 2 * i + 1 < array.Length; i++)
{
byte temp = array[2 * i];
array[2 * i] = array[2 * i + 1];
array[2 * i + 1] = temp;
}
return array;
}
public List<string> GetValueByTypeStringList(string typeStr, string address, ushort length)
{
switch (typeStr.ToUpper())
{
case "BOOL":
return this.ReadBool(address, length)?.Select<bool, string>(bVal => bVal.ToString()).ToList();
case "INT_16":
case "INT":
case "SINT":
case "SHORT":
case "WORD":
case "BYTE":
return this.ReadInt16(address, length)?.Select<short, string>(val => val.ToString()).ToList();
case "USINT":
case "UINT":
return this.ReadUInt16(address, length)?.Select<ushort, string>(val => val.ToString()).ToList();
case "DWORD":
case "DINT":
return this.ReadInt32(address, length)?.Select<int, string>(val => val.ToString()).ToList();
case "UDINT":
return this.ReadUInt32(address, length)?.Select<uint, string>(val => val.ToString()).ToList();
case "LWORD":
case "LINT":
return this.ReadInt64(address, length)?.Select<long, string>(val => val.ToString()).ToList();
case "ULINT":
return this.ReadUInt64(address, length)?.Select<ulong, string>(val => val.ToString()).ToList();
case "TIME":
case "REAL":
case "FLOAT":
return this.ReadFloat(address, length)?.Select<float, string>(val => val.ToString()).ToList();
case "LREAL":
case "DOUBLE":
return this.ReadDouble(address, length)?.Select<double, string>(val => val.ToString()).ToList();
default:
throw new IndexOutOfRangeException($"该类型的PLC地址{typeStr.ToUpper()}尚未定义转换类型!");
}
}
/// <summary>
/// 默认直接用数据库中的类型,如果是手动选择的,不要用
/// </summary>
/// <param name="typeStr"></param>
/// <param name="address"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool SetValueByTypeString(string typeStr, string address, string value)
{
switch (typeStr.ToUpper())
{
case "BOOL":
return this.WriteBool(address, Convert.ToBoolean(short.Parse(value)));
case "INT_16":
case "INT":
case "SINT":
case "SHORT":
case "WORD":
case "BYTE":
return this.WriteInt16(address, short.Parse(value));
case "USINT":
case "UINT":
return this.WriteUInt16(address, ushort.Parse(value));
case "DWORD":
case "DINT":
return this.WriteInt32(address, int.Parse(value));
case "UDINT":
return this.WriteUInt32(address, uint.Parse(value));
case "LWORD":
case "LINT":
return this.WriteInt64(address, long.Parse(value));
case "ULINT":
return this.WriteUInt64(address, ulong.Parse(value));
case "TIME":
case "REAL":
case "FLOAT":
return this.WriteFloat(address, float.Parse(value));
case "LREAL":
case "DOUBLE":
return this.WriteDouble(address, double.Parse(value));
default:
throw new IndexOutOfRangeException("该类型的PLC地址尚未定义转换类型!");
}
}
}
public class Modbus_PLC : Hmx_PLCBase, IPLCBase
{
#region 目前还没用上
public UInt16 Site { get; set; } = 2;
public UInt16 ConnTimeout { get; set; } = 300;
#endregion
/// <summary>
/// 获取参数值
/// </summary>
/// <typeparam name="TParam">参数类型</typeparam>
/// <param name="Params"></param>
/// <param name="paramName">参数名</param>
/// <returns>参数值</returns>
public static TParam Get<TParam>(ConnectionParamDictionary Params, string paramName)
{
TParam result;
try
{
if (typeof(TParam).IsEnum)
{
result = (TParam)Enum.Parse(typeof(TParam), Params[paramName.ToLower()]);
}
else
{
result = (TParam)Convert.ChangeType(Params[paramName.ToLower()], typeof(TParam));
}
}
catch (Exception ex)
{
throw new ArgumentException($@"获取参数失败,异常:{ex},参数名:{paramName}");
}
return result;
}
public Modbus_PLC(string ip, ushort port, byte node = 1)
{
IP = ip;
Port = port;
Node = node;
}
/// <summary>
/// 从机号
/// </summary>
private Byte Node { get; set; } = 1;
public enum EHcOperate { Read, Write }
public enum EHcCmd
{
ReadQ = 0x01,
ReadI = 0x02,
ReadM = 0x03,
WriteQ = 0x05,
WriteM = 0x06,
WriteQs = 0x0F,
WriteMs = 0x10,
}
public enum EHcAddrType { QX, IX, MX, MW, MD };
public class HcAddrInfo
{
public EHcOperate opt { get; set; } = EHcOperate.Read;
public EHcCmd cmd { get; set; } = EHcCmd.ReadQ;
public EValueType valueType { get; set; } = EValueType._BOOL;
public EHcAddrType addrType { get; set; } = EHcAddrType.QX;
public string addrStr { get; set; } = "";
public UInt16 addrValue { get; set; } = 0;
public UInt16 count { get; set; } = 0;
public UInt16 mwCount { get; set; } = 0;
public UInt16 mwOffset { get; set; } = 0;
}
private List<byte> header = new List<byte>();
//只处理M区
public List<T> ParseReadRecv<T>(byte[] recvmsg, HcAddrInfo addrInfo, ref List<T> rst, EValueType valueType)
{
switch (valueType)
{
case EValueType._BOOL:
{
int recvSize = recvmsg.Count();
int dataLen = (addrInfo.count + addrInfo.mwOffset + 15) / 16 * 2;
List<byte> dataByte = new List<byte>();
List<bool> dataBool = new List<bool>();
if (recvSize == dataLen + 9)
{
//两个两个的转
for (int i = 0; i < dataLen; i += 2)
{
dataByte.AddRange(recvmsg.Skip(9 + i).Take(2).Reverse().ToArray());
}
BitArray ba = new BitArray(dataByte.ToArray());
foreach (var item in ba) { dataBool.Add((bool)item); }
List<bool> result = dataBool.Skip(addrInfo.mwOffset).Take(addrInfo.count).ToList();
for (int i = 0; i < result.Count; i++)
{
rst.Add((T)(Object)result[i]);
}
}
}
break;
case EValueType._INT16:
{
int recvSize = recvmsg.Count();
int dataLen = addrInfo.mwCount * 2;
if (recvSize == dataLen + 9)
{
for (int i = recvSize - dataLen; i < recvSize; i += 2)
{
rst.Add((T)(Object)BitConverter.ToInt16(recvmsg.Skip(i).Take(2).Reverse().ToArray(), 0));
}
}
}
break;
case EValueType._UINT16:
{
int recvSize = recvmsg.Count();
int dataLen = addrInfo.mwCount * 2;
if (recvSize == dataLen + 9)
{
for (int i = recvSize - dataLen; i < recvSize; i += 2)
{
rst.Add((T)(Object)BitConverter.ToUInt16(recvmsg.Skip(i).Take(2).Reverse().ToArray(), 0));
}
}
}
break;
case EValueType._INT32:
{
int recvSize = recvmsg.Count();
int dataLen = addrInfo.mwCount * 2;
if (recvSize == dataLen + 9)
{
for (int i = recvSize - dataLen; i < recvSize; i += 4)
{
var bytes = recvmsg.Skip(i).Take(8).ToArray();
if (bytes.Length != 4)
return rst;
bytes = FormatConversion(bytes);
rst.Add((T)(Object)BitConverter.ToInt32(bytes, 0));
}
}
}
break;
case EValueType._INT64:
{
int recvSize = recvmsg.Count();
int dataLen = addrInfo.mwCount * 2;
if (recvSize == dataLen + 9)
{
for (int i = recvSize - dataLen; i < recvSize; i += 8)
{
var bytes = recvmsg.Skip(i).Take(8).ToArray();
if (bytes.Length != 8)
return rst;
bytes = FormatConversion(bytes);
rst.Add((T)(Object)BitConverter.ToInt64(bytes, 0));
}
}
}
break;
case EValueType._FLOAT:
{
int recvSize = recvmsg.Count();
int dataLen = addrInfo.mwCount * 2;
if (recvSize == dataLen + 9)
{
for (int i = recvSize - dataLen; i < recvSize; i += 4)
{
var bytes = recvmsg.Skip(i).Take(8).ToArray();
if (bytes.Length != 4)
return rst;
bytes = FormatConversion(bytes);
rst.Add((T)(Object)BitConverter.ToSingle(bytes, 0));
}
}
}
break;
case EValueType._DOUBLE:
{
int recvSize = recvmsg.Count();
int dataLen = addrInfo.mwCount * 2;
if (recvSize == dataLen + 9)
{
for (int i = recvSize - dataLen; i < recvSize; i += 8)
{
var bytes = recvmsg.Skip(i).Take(8).ToArray();
if (bytes.Length != 8)
return rst;
bytes = FormatConversion(bytes);
rst.Add((T)(Object)BitConverter.ToDouble(bytes, 0));
}
}
}
break;
case EValueType._STRING:
{
int recvSize = recvmsg.Count();
int dataLen = addrInfo.mwCount * 2;
// if (recvSize == dataLen + 9)
if (recvSize > 9)
{
rst.Add((T)(Object)System.Text.Encoding.UTF8.GetString(recvmsg.Skip(9).ToArray()));
}
}
break;
default:
break;
}
return rst;
}
public byte[] getReadSend(HcAddrInfo addrInfo)
{
Byte[] rst;
List<byte> data = new List<byte>();
data.Add(Node); // 从机地址
data.Add((byte)addrInfo.cmd); // 指令
data.AddRange(BitConverter.GetBytes(addrInfo.addrValue).Reverse()); // 地址
if (addrInfo.addrType == EHcAddrType.MX ||
addrInfo.addrType == EHcAddrType.MW)
data.AddRange(BitConverter.GetBytes((ushort)addrInfo.mwCount).Reverse()); // 数量
else
data.AddRange(BitConverter.GetBytes(addrInfo.count).Reverse()); // 数量
List<byte> send = new List<byte>();
send.AddRange(new byte[] { 0x00, 0x00 }); // 事务标识符;
send.AddRange(new byte[] { 0x00, 0x00 }); // 协议标识符;
send.AddRange(BitConverter.GetBytes((ushort)data.Count()).Reverse()); // 长度;
send.AddRange(data);
rst = send.ToArray();
return rst;
}
public HcAddrInfo ConvertToAddr(string addr, ushort count, EValueType valueType, EHcOperate opt, bool isMulti = true)
{
// [1] 地址信息赋值
HcAddrInfo rst = new HcAddrInfo() { opt = opt, count = count, valueType = valueType, addrStr = addr };
// [2] 分离前缀与地址
String addrTypeStr = "";
String addrValueStr = "";
Regex r = new Regex("[A-Za-z]+");
var m = r.Match(addr);
if (m.Success)
addrTypeStr = m.Groups[0].ToString();
addrValueStr = addr.Remove(0, addrTypeStr.Length);
// [3] 解析地址类型
switch (addrTypeStr)
{
case "MX":
{
rst.cmd = EHcOperate.Read == opt ? EHcCmd.ReadM : EHcCmd.WriteM;
var num = addrValueStr.Split('.');
if (num.Count() == 1)
rst.mwOffset = Convert.ToInt32(num[0]) % 2 == 0 ? (ushort)0 : (ushort)8;
else if (num.Count() == 2)
rst.mwOffset = Convert.ToInt32(num[0]) % 2 == 0 ? Convert.ToUInt16(num[1]) : (ushort)(Convert.ToUInt16(num[1]) + 8);
rst.addrType = EHcAddrType.MX;
rst.addrValue = (ushort)((Convert.ToInt32(num[0]) / 2));
rst.mwCount = (ushort)((rst.count + rst.mwOffset + 15) / 16);
}
break;
case "MB":
{
rst.cmd = EHcOperate.Read == opt ? EHcCmd.ReadM : EHcCmd.WriteM;
var num = addrValueStr.Split('.');
if (num.Count() == 1)
rst.mwOffset = Convert.ToInt32(num[0]) % 2 == 0 ? (ushort)0 : (ushort)8;
else if (num.Count() == 2)
rst.mwOffset = Convert.ToInt32(num[0]) % 2 == 0 ? Convert.ToUInt16(num[1]) : (ushort)(Convert.ToUInt16(num[1]) + 8);
rst.addrType = EHcAddrType.MX;
rst.addrValue = (ushort)((Convert.ToInt32(num[0]) / 2));
rst.mwCount = (ushort)((rst.count + rst.mwOffset + 15) / 16);
}
break;
case "MW":
{
if (EHcOperate.Read == opt)
rst.cmd = EHcCmd.ReadM;
else
rst.cmd = isMulti ? EHcCmd.WriteMs : EHcCmd.WriteM;
switch (rst.valueType)
{
case EValueType._INT16: rst.mwCount = 1; break;
case EValueType._INT32: rst.mwCount = 2; break;
case EValueType._INT64: rst.mwCount = 4; break;
case EValueType._UINT16: rst.mwCount = 1; break;
case EValueType._UINT32: rst.mwCount = 2; break;
case EValueType._UINT64: rst.mwCount = 4; break;
case EValueType._FLOAT: rst.mwCount = 2; break;
case EValueType._DOUBLE: rst.mwCount = 4; break;
case EValueType._STRING: rst.mwCount = 1; break;
}
rst.mwCount = (ushort)(rst.mwCount * count);
rst.addrType = EHcAddrType.MW;
rst.addrValue = Convert.ToUInt16(addrValueStr);
}
break;
default:
break;
}
return rst;
}
private bool SocketSend(byte[] array, ref int recvlen, ref byte[] recvmsg)
{
mutex.WaitOne();
try
{
if (array.Length != SocketClient.Send(array))
return false;
recvlen = SocketClient.Receive(recvmsg);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
mutex.ReleaseMutex();
return true;
}
#region 写方法
public bool WriteInt32(String addr, int value)
{
return WriteValue(addr, value, EValueType._INT32);
}
public bool WriteInt16(String addr, short value)
{
return WriteValue(addr, value, EValueType._INT16);
}
public bool WriteBool(String addr, bool value)
{
return WriteValue(addr, value, EValueType._BOOL);
}
public bool WriteFloat(String addr, float value)
{
return WriteValue(addr, value, EValueType._FLOAT);
}
public bool WriteDouble(String addr, Double value)
{
return WriteValue(addr, value, EValueType._DOUBLE);
}
public bool WriteString(String addr, string value)
{
return WriteValue(addr, value, EValueType._STRING);
}
public bool WriteValue(String addr, object value, EValueType valueType, bool IsMult = true)
{
bool rst = false;
if (!IsConnect)
return rst;
var addrInfo = ConvertToAddr(addr, 1, valueType, EHcOperate.Write, IsMult);
var sendInfo = GetWriteSend(addrInfo, value, valueType);
byte[] recvmsg = new byte[65535];
int len = 0;
SocketSend(sendInfo, ref len, ref recvmsg);
rst = parseWriteRecv(recvmsg);
return rst;
}
public Byte[] GetWriteSend(HcAddrInfo addrInfo, object value, EValueType valueType)
{
Byte[] rst;
List<byte> data = new List<byte>();
data.Add(Node); // 从机地址
data.Add((Byte)addrInfo.cmd); // 指令
data.AddRange(BitConverter.GetBytes(addrInfo.addrValue).Reverse()); // 地址高位
switch (valueType)
{
case EValueType._BOOL:
{
List<short> temp = new List<short>();
var ret = ReadValue(addrInfo.addrStr, 1, EValueType._INT16, ref temp);
var bits = BitConverter.GetBytes(ret[0]);
BitArray bitSet = new BitArray(bits);
bitSet[addrInfo.mwOffset] = (bool)value;
bitSet.CopyTo(bits, 0); //复制 8 个bit
data.AddRange(bits.Reverse());
}
break;
case EValueType._INT16:
{
//data.AddRange(BitConverter.GetBytes(Convert.ToInt16(value)).Reverse());
data.AddRange(BitConverter.GetBytes((ushort)addrInfo.mwCount).Reverse()); // 数量高位
data.Add((byte)(addrInfo.mwCount * 2)); // 字节数
data.AddRange(BitConverter.GetBytes(Convert.ToInt16(value)).Reverse());
}
break;
case EValueType._INT32:
{
data.AddRange(BitConverter.GetBytes((ushort)addrInfo.mwCount).Reverse()); // 数量高位
data.Add((byte)(addrInfo.mwCount * 2)); // 字节数
var temp = BitConverter.GetBytes(Convert.ToInt32(value));
temp = FormatConversion(temp);
data.AddRange(temp);
}
break;
case EValueType._INT64:
{
data.AddRange(BitConverter.GetBytes((ushort)addrInfo.mwCount).Reverse()); // 数量高位
data.Add((byte)(addrInfo.mwCount * 2)); // 字节数
var temp = BitConverter.GetBytes(Convert.ToInt64(value));
temp = FormatConversion(temp);
data.AddRange(temp);
}
break;
case EValueType._FLOAT:
{
data.AddRange(BitConverter.GetBytes((ushort)addrInfo.mwCount).Reverse()); // 数量高位
data.Add((byte)(addrInfo.mwCount * 2)); // 字节数
//data.AddRange(BitConverter.GetBytes(Convert.ToSingle(value)).Reverse());
var temp = BitConverter.GetBytes(Convert.ToSingle(value));
temp = FormatConversion(temp);
data.AddRange(temp);
}
break;
case EValueType._DOUBLE:
{
data.AddRange(BitConverter.GetBytes((ushort)addrInfo.mwCount).Reverse()); // 数量高位
data.Add((byte)(addrInfo.mwCount * 2)); // 字节数
var temp = BitConverter.GetBytes(Convert.ToDouble(value));
temp = FormatConversion(temp);
data.AddRange(temp);
}
break;
case EValueType._STRING:
{
var valueTemp = System.Text.Encoding.UTF8.GetBytes(value.ToString()).ToList();
if (valueTemp.Count() % 2 != 0)
valueTemp.Add((byte)0);
data.AddRange(BitConverter.GetBytes((ushort)(valueTemp.Count() / 2)).Reverse()); // 数量高位
//data.Add((byte)(valueTemp.Count()/2 == 0? valueTemp.Count() : valueTemp.Count() + 1)); // 字节数
data.Add((byte)(valueTemp.Count())); // 字节数
data.AddRange(valueTemp);
}
break;
default:
break;
}
byte[] placeholder = new byte[] { 0x00, 0x00 };
ushort dataLen = (ushort)data.Count();
List<byte> send = new List<byte>();
send.AddRange(placeholder); // 事务标识符;
send.AddRange(placeholder); // 协议标识符;
send.AddRange(BitConverter.GetBytes(dataLen).Reverse()); // 长度;
send.AddRange(data);
rst = send.ToArray();
return rst;
}
public bool parseWriteRecv(byte[] recv)
{
bool rst = true;
int errTypeIndex = 7;
int errCodeIndex = 8;
if (recv.Count() == 9)
{
if (recv[errTypeIndex] >= 0x80)
{
var type = recv[errTypeIndex] - 0x80;
var code = BitConverter.ToInt32(recv, errCodeIndex);
rst = false;
}
}
return rst;
}
#endregion
#region 读方法
public List<bool> ReadBools(string addr, ushort count)
{
List<bool> rst = new List<bool>();
var ret = ReadValue(addr, count, EValueType._BOOL, ref rst);
return ret;
}
public bool ReadBool(string addr)
{
List<bool> rst = new List<bool>();
var ret = ReadValue(addr, 1, EValueType._BOOL, ref rst);
return rst.Count() > 0 ? ret[0] : false;
}
public List<short> ReadInt16s(string addr, ushort len)
{
List<short> rst = new List<short>();
var ret = ReadValue(addr, len, EValueType._INT16, ref rst);
return rst;
}
public short ReadInt16(string addr)
{
List<short> rst = new List<short>();
var ret = ReadValue(addr, 1, EValueType._INT16, ref rst);
return rst.Count() > 0 ? ret[0] : (short)0;
}
public List<int> ReadInts(string addr, ushort len)
{
List<int> rst = new List<int>();
var ret = ReadValue(addr, len, EValueType._INT32, ref rst);
return rst;
}
public int ReadInt(string addr)
{
List<int> rst = new List<int>();
var ret = ReadValue(addr, 1, EValueType._INT32, ref rst);
return rst.Count() > 0 ? ret[0] : 0;
}
public List<long> ReadInt64s(string addr, ushort len)
{
List<long> rst = new List<long>();
var ret = ReadValue(addr, len, EValueType._INT64, ref rst);
return rst;
}
public long ReadInt64(string addr)
{
List<long> rst = new List<long>();
var ret = ReadValue(addr, 1, EValueType._INT64, ref rst);
return rst.Count() > 0 ? ret[0] : (long)0;
}
public List<float> ReadFloats(string addr, ushort len)
{
List<float> rst = new List<float>();
var ret = ReadValue(addr, len, EValueType._FLOAT, ref rst);
return rst;
}
public float ReadFloat(string addr)
{
List<float> rst = new List<float>();
var ret = ReadValue(addr, 1, EValueType._FLOAT, ref rst);
return rst.Count() > 0 ? ret[0] : (float)0;
}
public List<Double> ReadDoubles(string addr, ushort len)
{
List<Double> rst = new List<Double>();
var ret = ReadValue(addr, len, EValueType._DOUBLE, ref rst);
return rst;
}
public Double ReadDouble(string addr)
{
List<Double> rst = new List<Double>();
var ret = ReadValue(addr, 1, EValueType._DOUBLE, ref rst);
return rst.Count() > 0 ? ret[0] : (Double)0;
}
public string ReadString(string addr, ushort len)
{
List<string> rst = new List<string>();
var ret = ReadValue(addr, len, EValueType._STRING, ref rst);
return rst.Count() > 0 ? ret[0] : "";
}
public List<byte> ReadAllByte(string addr, UInt16 count = 65535)
{
List<byte> rst = new List<byte>();
var ret = ReadValue(addr, count, EValueType._STRING, ref rst);
return rst;
}
public List<T> ReadValue<T>(string addr, ushort count, EValueType valueType, ref List<T> rst)
{
if (!IsConnect)
return rst;
if (count <= 0)
return rst;
var addrInfo = ConvertToAddr(addr, count, valueType, EHcOperate.Read, false);
var sendInfo = getReadSend(addrInfo);
Console.WriteLine(BitConverter.ToString(sendInfo));
int len = 0;
byte[] recvmsg = new byte[1024];
SocketSend(sendInfo, ref len, ref recvmsg);
ParseReadRecv(recvmsg.Take(len).ToArray(), addrInfo, ref rst, valueType);
return rst;
}
#endregion
//public List<byte> ReadAllByte(string addr, ushort count = ushort.MaxValue)
//{
// throw new NotImplementedException();
//}
public ushort ReadUInt16(string addr)
{
throw new NotImplementedException();
}
public List<ushort> ReadUInt16s(string addr, ushort count)
{
List<UInt16> rst = new List<UInt16>();
var ret = ReadValue(addr, count, EValueType._UINT16, ref rst);
return rst.Count() > 0 ? ret : null;
}
public string ReadString(string addr, ushort count, bool stringFormate = true)
{
List<string> rst = new List<string>();
var ret = ReadValue(addr, count, EValueType._STRING, ref rst);
return rst.Count() > 0 ? ret[0] : "ERROR";
}
public int ReadInt32(string addr)
{
List<int> rst = new List<int>();
var ret = ReadValue(addr, 1, EValueType._INT32, ref rst);
return rst.Count() > 0 ? ret[0] : 0;
}
public List<int> ReadInt32s(string addr, ushort count)
{
List<int> rst = new List<int>();
var ret = ReadValue(addr, count, EValueType._INT32, ref rst);
return rst.Count() == count ? rst : new List<int>();
}
public uint ReadUInt32(string addr)
{
List<uint> rst = new List<uint>();
var ret = ReadValue(addr, 1, EValueType._UINT32, ref rst);
return rst.Count() > 0 ? ret[0] : 0;
}
public List<uint> ReadUInt32s(string addr, ushort count)
{
List<uint> rst = new List<uint>();
var ret = ReadValue(addr, count, EValueType._UINT32, ref rst);
return rst.Count() == count ? rst : new List<uint>();
}
public ulong ReadUInt64(string addr)
{
List<UInt64> rst = new List<UInt64>();
var ret = ReadValue(addr, 1, EValueType._UINT64, ref rst);
return rst.Count() > 0 ? ret[0] : 0;
}
public List<ulong> ReadUInt64s(string addr, ushort count)
{
List<UInt64> rst = new List<UInt64>();
var ret = ReadValue(addr, count, EValueType._UINT64, ref rst);
return rst.Count() == count ? rst : new List<UInt64>();
}
public bool WriteBools(string addr, List<bool> value)
{
throw new NotImplementedException();
}
public bool WriteInt16s(string addr, List<short> value)
{
throw new NotImplementedException();
}
public bool WriteUInt16(string addr, ushort value)
{
throw new NotImplementedException();
}
public bool WriteUInt16s(string addr, List<ushort> value)
{
throw new NotImplementedException();
}
public bool WriteInt32s(string addr, List<int> value)
{
throw new NotImplementedException();
}
public bool WriteUInt32(string addr, uint value)
{
return true;
throw new NotImplementedException();
}
public bool WriteUInt32s(string addr, List<uint> value)
{
throw new NotImplementedException();
}
public bool WriteInt64(string addr, long value)
{
throw new NotImplementedException();
}
public bool WriteInt64s(string addr, List<long> value)
{
throw new NotImplementedException();
}
public bool WriteUInt64(string addr, ulong value)
{
throw new NotImplementedException();
}
public bool WriteUInt64s(string addr, List<ulong> value)
{
throw new NotImplementedException();
}
public bool WriteDoubles(string addr, List<double> value)
{
throw new NotImplementedException();
}
public bool WriteFloats(string addr, List<float> value)
{
throw new NotImplementedException();
}
/// <summary>
/// 写入PLC的值
/// </summary>
public string WriteValues;
/// <summary>
/// 写地址
/// </summary>
public string WriteAddress;
/// <summary>
/// 读地址
/// </summary>
public string ReadAddress;
/// <summary>
/// 读取长度(非字符串)
/// </summary>
public string Count;
/// <summary>
/// 读取字符长度
/// </summary>
public string NumberLength;
/// <summary>
/// 读取记录
/// </summary>
public string ReadLog;
}
Job数采实例
表格存储 安装NuGet组件:EPPlus4.5
public class ExcelHelper
{
public static string GetExcelFilePath(string filename)
{
// 获取当前日期并创建文件夹路径
var directory = Path.Combine("D:", "HYMSON", DateTime.Now.ToString("yyyy-MM-dd"));
// 创建目录(如果目录不存在)
Directory.CreateDirectory(directory);
// 返回文件的完整路径(文件名为当前日期)
return Path.Combine(directory, $"{filename+"_"+ DateTime.Now.ToString("yyyy-MM-dd")}.xlsx");
}
public static void CreateAExcelFile(string filePath)
{
// 创建 Excel 文件并添加表头
using (var package = new ExcelPackage(new FileInfo(filePath)))
{
var worksheet = package.Workbook.Worksheets.Add("Data");
worksheet.Cells[1, 1].Value = "时间";
worksheet.Cells[1, 2].Value = "长";
worksheet.Cells[1, 3].Value = "隙";
worksheet.Cells[1, 4].Value = "条码";
package.Save();
}
}
public static void CreateBExcelFile(string filePath)
{
// 创建 Excel 文件并添加表头
using (var package = new ExcelPackage(new FileInfo(filePath)))
{
var worksheet = package.Workbook.Worksheets.Add("Data");
worksheet.Cells[1, 1].Value = "时间";
worksheet.Cells[1, 2].Value = "实时值";
worksheet.Cells[1, 3].Value = "实时值";
worksheet.Cells[1, 4].Value = "条码";
package.Save();
}
}
public static void AppendDataToExcel(string filePath, DateTime time, float param1, float param2, string productCode)
{
using (var package = new ExcelPackage(new FileInfo(filePath)))
{
var worksheet = package.Workbook.Worksheets[0];
var row = worksheet.Dimension.Rows + 1; // 获取下一行的行号
worksheet.Cells[row, 1].Value = time.ToString();
worksheet.Cells[row, 2].Value = param1.ToString("0.00");
worksheet.Cells[row, 3].Value = param2.ToString("0.00");
worksheet.Cells[row, 4].Value = productCode;
package.Save();
}
}
}
使用:
IPLC.Instance._iPLC = new Modbus_PLC("127.0.0.1",(ushort)502,1);
IPLC.Instance.Connect();
[BackgroundJobDefine(cron: "*/1 * * * * ? *", "每3秒都执行")]
public class Interval_Job : PFBackgroundJob
{
private readonly string _excelAFilePath;
private readonly string _excelBFilePath;
private readonly IA_ProductOutputService _a_productOutputService;
private readonly IB_ProductOutputService _b_productOutputService;
public Interval_Job(IA_ProductOutputService a_productOutputService, IB_ProductOutputService b_productOutputService)
{
_a_productOutputService = a_productOutputService;
_b_productOutputService = b_productOutputService;
_excelAFilePath = ExcelHelper.GetExcelFilePath("测长");
if (!File.Exists(_excelAFilePath))
{
ExcelHelper.CreateAExcelFile(_excelAFilePath);
}
_excelBFilePath = ExcelHelper.GetExcelFilePath("对位");
if (!File.Exists(_excelBFilePath))
{
ExcelHelper.CreateAExcelFile(_excelBFilePath);
}
CleanOldDirectories();
}
protected override async Task HandleAsync()
{
//写入 PLC 数据
/* IPLC.Instance.WriteFloat("MW6000", 12.6f);
IPLC.Instance.WriteFloat("MW6100", 12.7f);
IPLC.Instance.WriteFloat("MW6204", 12.8f);
IPLC.Instance.WriteFloat("MW6304", 12.9f);
IPLC.Instance.WriteBool("MX3000.4", true);
IPLC.Instance.WriteBool("MX3000.5", true);*/
var flagA = IPLC.Instance.ReadBool("MX3000.4");
var flagB = IPLC.Instance.ReadBool("MX3000.5");
float paintLong = 0, interval = 0, tail = 0, head = 0;
// 根据 flagA 和 flagB 判断是否需要读取其他数据
if (flagA)
{
paintLong = IPLC.Instance.ReadFloat("MW6000");
interval = IPLC.Instance.ReadFloat("MW6100");
IPLC.Instance.WriteBool("MX3000.4", false);
var pro = await GetProductCode();
ExcelHelper.AppendDataToExcel(_excelAFilePath, DateTime.Now, paintLong, interval, pro);
}
if (flagB)
{
tail = IPLC.Instance.ReadFloat("MW6204");
head = IPLC.Instance.ReadFloat("MW6304");
IPLC.Instance.WriteBool("MX3000.4", false);
var pro = await GetProductCode();
ExcelHelper.AppendDataToExcel(_excelBFilePath, DateTime.Now, tail, head, pro );
}
}
public async Task<string> GetProductCode()
{
//是否生产
bool AhasPOut = await this._a_productOutputService.IsProductionInAsync();
bool BhasPOut = await this._b_productOutputService.IsProductionInAsync();
var pro = string.Empty;
if ((AhasPOut || BhasPOut))
{
if (AhasPOut)
{
pro = (await _a_productOutputService.GetProductionInAsync()).ProductCode;
}
if (BhasPOut)
{
pro = (await _b_productOutputService.GetProductionInAsync()).ProductCode;
}
}
return pro;
}
private void CleanOldDirectories()
{
var baseDirectory = Path.Combine("D:", "存放文件夹名称");
var directoryInfo = new DirectoryInfo(baseDirectory);
// 获取当前日期
DateTime sixMonthsAgo = DateTime.Now.AddMonths(-6);
// 遍历所有的子目录
foreach (var directory in directoryInfo.GetDirectories())
{
// 判断文件夹的创建时间
if (directory.CreationTime < sixMonthsAgo)
{
try
{
directory.Delete(true); // true 表示递归删除
}
catch (Exception ex)
{
Console.WriteLine($"Failed to delete directory {directory.Name}: {ex.Message}");
}
}
}
}
}
1823

被折叠的 条评论
为什么被折叠?



