|
|
using System;
|
|
|
using System.IO;
|
|
|
using System.Runtime.Serialization.Formatters.Binary;
|
|
|
using System.Runtime.Serialization;
|
|
|
using System.Threading.Tasks;
|
|
|
using HighWayIot.Log4net;
|
|
|
using HslCommunication;
|
|
|
using HslCommunication.Profinet.Melsec;
|
|
|
using System.Diagnostics;
|
|
|
using System.Linq;
|
|
|
|
|
|
namespace HighWayIot.Plc
|
|
|
{
|
|
|
public class PlcConnect
|
|
|
{
|
|
|
//private static readonly Lazy<PlcConnect> lazy = new Lazy<PlcConnect>(() => new PlcConnect());
|
|
|
|
|
|
//public static PlcConnect Instance
|
|
|
//{
|
|
|
// get
|
|
|
// {
|
|
|
// return lazy.Value;
|
|
|
// }
|
|
|
//}
|
|
|
|
|
|
private static LogHelper logHelper = LogHelper.Instance;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 静态懒加载MelsecMcNet2 读取 CPU
|
|
|
/// </summary>
|
|
|
public static readonly MelsecMcNet MelsecInstance1 = CreateAb("192.168.0.10", 2001);
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 静态懒加载MelsecMcNet2 写入 CPU
|
|
|
/// </summary>
|
|
|
public static readonly MelsecMcNet MelsecInstance2 = CreateAb("192.168.0.10", 2002);
|
|
|
|
|
|
/// <summary>
|
|
|
/// 锁对象写
|
|
|
/// </summary>
|
|
|
private static readonly object lockerWrite = new object();
|
|
|
|
|
|
/// <summary>
|
|
|
/// 锁对象读
|
|
|
/// </summary>
|
|
|
private static readonly object lockerRead = new object();
|
|
|
|
|
|
|
|
|
|
|
|
private PlcConnect()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 初始化三菱的服务器
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
private static MelsecMcNet CreateAb(string ip, int port)
|
|
|
{
|
|
|
//string Ip = ;
|
|
|
MelsecMcNet plc = new MelsecMcNet();
|
|
|
try
|
|
|
{
|
|
|
plc.CommunicationPipe = new HslCommunication.Core.Pipe.PipeTcpNet(ip, port)
|
|
|
{
|
|
|
ConnectTimeOut = 3000, // 连接超时时间,单位毫秒
|
|
|
ReceiveTimeOut = 2000, // 接收超时时间,单位毫秒
|
|
|
SleepTime = 0,
|
|
|
SocketKeepAliveTime = -1,
|
|
|
IsPersistentConnection = true,
|
|
|
};
|
|
|
|
|
|
OperateResult result;
|
|
|
result = plc.ConnectServer();
|
|
|
logHelper.Info($"Plc连接 信息:[{result.Message}] 错误代码:[{result.ErrorCode}]");
|
|
|
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error("初始化PLC服务器发生错误!", ex);
|
|
|
}
|
|
|
|
|
|
return plc;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// PLC2写入数据
|
|
|
/// </summary>
|
|
|
/// <param name="address">地址</param>
|
|
|
/// <param name="value">值</param>
|
|
|
/// <param name="type">数据类型</param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult PlcWrite2(string address, object value, DataTypeEnum type)
|
|
|
{
|
|
|
var result = new OperateResult() { IsSuccess = false };
|
|
|
try
|
|
|
{
|
|
|
lock (lockerWrite)
|
|
|
{
|
|
|
//Stopwatch swWrite = new Stopwatch();
|
|
|
//swWrite.Start();
|
|
|
switch (type)
|
|
|
{
|
|
|
case DataTypeEnum.Bool:
|
|
|
result = MelsecInstance1.Write(address, Convert.ToBoolean(value));
|
|
|
break;
|
|
|
case DataTypeEnum.Byte:
|
|
|
result = MelsecInstance1.Write(address, Convert.ToByte(value));
|
|
|
break;
|
|
|
//case DataTypeEnum.Bytes:
|
|
|
// result = MelsecInstance1.Write(address, ObjectToBytes(value));
|
|
|
// break;
|
|
|
case DataTypeEnum.Int16:
|
|
|
result = MelsecInstance1.Write(address, Convert.ToInt16(value));
|
|
|
break;
|
|
|
case DataTypeEnum.UInt16:
|
|
|
result = MelsecInstance1.Write(address, Convert.ToUInt16(value));
|
|
|
break;
|
|
|
case DataTypeEnum.Int32:
|
|
|
result = MelsecInstance1.Write(address, Convert.ToInt32(value));
|
|
|
break;
|
|
|
case DataTypeEnum.UInt32:
|
|
|
result = MelsecInstance1.Write(address, Convert.ToUInt32(value));
|
|
|
break;
|
|
|
case DataTypeEnum.Int64:
|
|
|
result = MelsecInstance1.Write(address, Convert.ToInt64(value));
|
|
|
break;
|
|
|
case DataTypeEnum.UInt64:
|
|
|
result = MelsecInstance1.Write(address, Convert.ToUInt64(value));
|
|
|
break;
|
|
|
case DataTypeEnum.Float:
|
|
|
result = MelsecInstance1.Write(address, Convert.ToSingle(value));
|
|
|
break;
|
|
|
case DataTypeEnum.Double:
|
|
|
result = MelsecInstance1.Write(address, Convert.ToDouble(value));
|
|
|
break;
|
|
|
case DataTypeEnum.String:
|
|
|
result = MelsecInstance1.Write(address, Convert.ToString(value));
|
|
|
break;
|
|
|
default:
|
|
|
throw new ArgumentException($"Unsupported data type: {type}");
|
|
|
}
|
|
|
//swWrite.Stop();
|
|
|
//logHelper.Info($"Write address:[{address}] value:[{value}] result:[{result.IsSuccess}] time:[{swWrite.ElapsedMilliseconds}]");
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error("PLC写入数据发生错误!", ex);
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 写入byte数组
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <param name="data"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult PlcWriteBytes2(string address, byte[] data)
|
|
|
{
|
|
|
OperateResult result = new OperateResult();
|
|
|
try
|
|
|
{
|
|
|
lock (lockerWrite)
|
|
|
{
|
|
|
result = MelsecInstance2.Write(address, data);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC2写入Bytes发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
// 将对象序列化为 byte 数组
|
|
|
public static byte[] ObjectToBytes(object obj)
|
|
|
{
|
|
|
using (MemoryStream ms = new MemoryStream())
|
|
|
{
|
|
|
IFormatter formatter = new BinaryFormatter();
|
|
|
formatter.Serialize(ms, obj);
|
|
|
return ms.ToArray();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 将 byte 数组反序列化为对象
|
|
|
public static object BytesToObject(byte[] bytes)
|
|
|
{
|
|
|
using (MemoryStream ms = new MemoryStream(bytes))
|
|
|
{
|
|
|
IFormatter formatter = new BinaryFormatter();
|
|
|
return formatter.Deserialize(ms);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 字符串读取2
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <param name="length"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult<string> ReadString2(string address, ushort length)
|
|
|
{
|
|
|
OperateResult<string> result = new OperateResult<string>();
|
|
|
try
|
|
|
{
|
|
|
lock (lockerRead)
|
|
|
{
|
|
|
result = MelsecInstance2.ReadString(address, length);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC2读取String发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取字节数组
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <param name="length"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult<byte[]> ReadByte2(string address, ushort length)
|
|
|
{
|
|
|
OperateResult<byte[]> result = new OperateResult<byte[]>();
|
|
|
try
|
|
|
{
|
|
|
lock (lockerRead)
|
|
|
{
|
|
|
//Stopwatch swRead = new Stopwatch();
|
|
|
//swRead.Start();
|
|
|
result = MelsecInstance2.Read(address, length);
|
|
|
//swRead.Stop();
|
|
|
//logHelper.Info($"Read address:[{address}] length:[{length}] result:[{result.IsSuccess}] time:[{swRead.ElapsedMilliseconds}]");
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC2读取bytes发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取bool
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult<bool> ReadBool2(string address)
|
|
|
{
|
|
|
OperateResult<bool> result = new OperateResult<bool>();
|
|
|
try
|
|
|
{
|
|
|
lock (lockerRead)
|
|
|
{
|
|
|
result = MelsecInstance2.ReadBool(address);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC读取Bool发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取Int16
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult<short> ReadInt162(string address)
|
|
|
{
|
|
|
OperateResult<short> result = new OperateResult<short>();
|
|
|
try
|
|
|
{
|
|
|
lock (lockerRead)
|
|
|
{
|
|
|
result = MelsecInstance2.ReadInt16(address);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC读取Int16发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取UInt16
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult<ushort> ReadUInt162(string address)
|
|
|
{
|
|
|
OperateResult<ushort> result = new OperateResult<ushort>();
|
|
|
try
|
|
|
{
|
|
|
lock (lockerRead)
|
|
|
{
|
|
|
result = MelsecInstance2.ReadUInt16(address);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC读取Int16发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取Int32
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult<int> ReadInt322(string address)
|
|
|
{
|
|
|
OperateResult<int> result = new OperateResult<int>();
|
|
|
try
|
|
|
{
|
|
|
lock (lockerRead)
|
|
|
{
|
|
|
result = MelsecInstance2.ReadInt32(address);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC读取Int16发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取UInt32
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult<uint> ReadUInt322(string address)
|
|
|
{
|
|
|
OperateResult<uint> result = new OperateResult<uint>();
|
|
|
try
|
|
|
{
|
|
|
lock (lockerRead)
|
|
|
{
|
|
|
result = MelsecInstance2.ReadUInt32(address);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC读取Int16发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取Int64
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult<long> ReadInt642(string address)
|
|
|
{
|
|
|
OperateResult<long> result = new OperateResult<long>();
|
|
|
try
|
|
|
{
|
|
|
lock(lockerRead)
|
|
|
{
|
|
|
result = MelsecInstance2.ReadInt64(address);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC读取Int16发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取UInt64
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult<ulong> ReadUInt642(string address)
|
|
|
{
|
|
|
OperateResult<ulong> result = new OperateResult<ulong>();
|
|
|
try
|
|
|
{
|
|
|
lock (lockerRead)
|
|
|
{
|
|
|
result = MelsecInstance2.ReadUInt64(address);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC读取Int16发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取Float
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult<float> ReadFloat2(string address)
|
|
|
{
|
|
|
OperateResult<float> result = new OperateResult<float>();
|
|
|
try
|
|
|
{
|
|
|
lock (lockerRead)
|
|
|
{
|
|
|
result = MelsecInstance2.ReadFloat(address);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC读取Float发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取Double
|
|
|
/// </summary>
|
|
|
/// <param name="address"></param>
|
|
|
/// <returns></returns>
|
|
|
public static OperateResult<double> ReadDouble2(string address)
|
|
|
{
|
|
|
OperateResult<double> result = new OperateResult<double>();
|
|
|
|
|
|
try
|
|
|
{
|
|
|
lock (lockerRead)
|
|
|
{
|
|
|
result = MelsecInstance2.ReadDouble(address);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logHelper.Error($"PLC读取Double发生错误!address:[{address}]", ex);
|
|
|
return default;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
}
|
|
|
} |