You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

461 lines
15 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
}
}
}