using Bro.Common.Base;
|
using Bro.Common.Helper;
|
using Bro.Common.Interface;
|
using Bro.Common.Model;
|
using Bro.Common.Model.Interface;
|
using System;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.IO;
|
using System.Linq;
|
using System.Net;
|
using System.Net.Sockets;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
|
namespace Bro.Device.OmronFins
|
{
|
public class OmronFinsDriver : PLCBase, IMonitor
|
{
|
#region PLCBase
|
public override void Read(PLCOperationConfigBase config)
|
{
|
}
|
|
public override void ReadItem(PLC_ITEM item)
|
{
|
if (opClient == null || !opClient.Connected)
|
{
|
InitialOpClient();
|
}
|
|
byte[] data = frame.GetSendReadFrameBytes(item, CurrentSid);
|
opStream.Write(data, 0, data.Length);
|
|
byte[] buffer = new byte[2048];
|
int readSize = opStream.Read(buffer, 0, buffer.Length);
|
|
if (readSize > 0)
|
{
|
List<int> list = frame.AnalyseReceivedItems(buffer.Take(readSize).ToArray(), item);
|
item.ITEM_VALUE = string.Join(",", list);
|
}
|
}
|
|
//public void ReadItem(PLC_ITEM item, TcpClient client)
|
//{
|
// if (client == null || !client.Connected)
|
// {
|
// InitialOpClient();
|
// }
|
|
// byte[] data = frame.GetSendReadFrameBytes(item, CurrentSid);
|
// client.GetStream().Write(data, 0, data.Length);
|
|
// byte[] buffer = client.Receive(ref plcEP);
|
// List<int> list = frame.AnalyseReceivedItems(buffer, item);
|
|
// item.ITEM_VALUE = string.Join(",", list);
|
//}
|
|
public override void Write(PLCOperationConfigBase config)
|
{
|
}
|
|
public override void WriteItem(PLC_ITEM item, bool waitForReply = true)
|
{
|
int repeatTime = 10;
|
Stopwatch sw = new Stopwatch();
|
sw.Start();
|
|
lock (opClientLock)
|
{
|
do
|
{
|
try
|
{
|
InitialOpClient();
|
|
byte[] data = frame.GetSendWriteFrameBytes(item, CurrentSid);
|
opStream.Write(data, 0, data.Length);
|
|
sw.Stop();
|
if (sw.ElapsedMilliseconds > 10)
|
{
|
LogAsync(DateTime.Now, $"发送完成,耗时:{sw.ElapsedMilliseconds}");
|
}
|
repeatTime = 0;
|
|
}
|
catch (Exception ex)
|
{
|
if (repeatTime > 0)
|
{
|
repeatTime--;
|
opClient.Close();
|
opClient = null;
|
}
|
else
|
{
|
LogAsync(DateTime.Now, "Send Exception:" + ex.GetExceptionMessage());
|
}
|
}
|
} while (repeatTime > 0);
|
|
if (waitForReply)
|
{
|
try
|
{
|
byte[] buffer = new byte[1024];
|
int bufferCount = opStream.Read(buffer, 0, buffer.Length);
|
if (bufferCount > 0)
|
{
|
frame.AnalyseReceivedItems(buffer.Take(bufferCount).ToArray(), item);
|
}
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, "写入反馈异常\r\n" + ex.GetExceptionMessage());
|
}
|
}
|
else
|
{
|
Task.Run(() =>
|
{
|
try
|
{
|
byte[] buffer = new byte[1024];
|
int bufferCount = opStream.Read(buffer, 0, buffer.Length);
|
if (bufferCount > 0)
|
{
|
frame.AnalyseReceivedItems(buffer.Take(bufferCount).ToArray(), item);
|
}
|
}
|
catch (Exception ex)
|
{
|
LogAsync(DateTime.Now, "写入反馈异常\r\n" + ex.GetExceptionMessage());
|
}
|
});
|
}
|
}
|
|
//item.ITEM_VALUE = string.Join(",", receiveFrame.BodyFrame.OpValue);
|
}
|
|
/// <summary>
|
/// 写单独地址
|
/// </summary>
|
/// <param name="address">10进制表示的地址,首位表示类型 例如 45000</param>
|
/// <param name="writeValue"></param>
|
/// <param name="waitForReply"></param>
|
public override void WriteSingleAddress(int address, int writeValue, bool waitForReply = true)
|
{
|
PLC_ITEM item = new PLC_ITEM();
|
item.OP_TYPE = 2;
|
|
//string addStr = address.ToString();
|
//string prefix = addStr[0].ToString();
|
//string after = int.Parse(addStr.Substring(1)).ToString("16");
|
|
item.ADDRESS = "D" + address.ToString();
|
item.ITEM_LENGTH = 1;
|
item.ITEM_VALUE = writeValue.ToString();
|
|
//lock (opClient)
|
{
|
WriteItem(item, waitForReply);
|
}
|
}
|
|
//public void WriteItem(PLC_ITEM item, TcpClient client, bool waitForReply = true)
|
//{
|
// int repeatTime = 10;
|
// Stopwatch sw = new Stopwatch();
|
// sw.Start();
|
// ModbusFrame_Send frame = new ModbusFrame_Send(item, IConfig.PLCUnitNum);
|
// sw.Stop();
|
// if (sw.ElapsedMilliseconds > 10)
|
// {
|
// LogAsync(DateTime.Now, $"构建Frame,耗时:{sw.ElapsedMilliseconds}");
|
// }
|
|
// NetworkStream stream = null;
|
|
// lock (opClientLock)
|
// {
|
// do
|
// {
|
// try
|
// {
|
// InitialOpClient();
|
|
// //Stopwatch sw = new Stopwatch();
|
// sw.Restart();
|
// LogAsync(DateTime.Now, frame);
|
// stream = opClient.GetStream();
|
// stream.Write(frame.Frame, 0, frame.Frame.Length);
|
// stream.Flush();
|
// sw.Stop();
|
// if (sw.ElapsedMilliseconds > 10)
|
// {
|
// LogAsync(DateTime.Now, $"发送完成,耗时:{sw.ElapsedMilliseconds}");
|
// }
|
// repeatTime = 0;
|
|
// }
|
// catch (Exception ex)
|
// {
|
// if (repeatTime > 0)
|
// {
|
// repeatTime--;
|
// opClient.Close();
|
// opClient = null;
|
// }
|
// else
|
// {
|
// LogAsync(DateTime.Now, "Send Exception:" + ex.GetExceptionMessage());
|
// }
|
// }
|
// } while (repeatTime > 0);
|
|
// if (waitForReply)
|
// {
|
// try
|
// {
|
// byte[] buffer = new byte[1024];
|
// int bufferCount = stream.Read(buffer, 0, buffer.Length);
|
// ModbusFrame_Receive receiveFrame = new ModbusFrame_Receive(buffer.Take(bufferCount).ToArray());
|
// LogAsync(DateTime.Now, receiveFrame);
|
// }
|
// catch (Exception ex)
|
// {
|
// LogAsync(DateTime.Now, "写入反馈异常\r\n" + ex.GetExceptionMessage());
|
// }
|
// }
|
// else
|
// {
|
// Task.Run(() =>
|
// {
|
// try
|
// {
|
// byte[] buffer = new byte[1024];
|
// int bufferCount = stream.Read(buffer, 0, buffer.Length);
|
// ModbusFrame_Receive receiveFrame = new ModbusFrame_Receive(buffer.Take(bufferCount).ToArray());
|
// LogAsync(DateTime.Now, receiveFrame);
|
// }
|
// catch (Exception ex)
|
// {
|
// LogAsync(DateTime.Now, "写入反馈异常\r\n" + ex.GetExceptionMessage());
|
// }
|
// });
|
// }
|
// }
|
|
// //item.ITEM_VALUE = string.Join(",", receiveFrame.BodyFrame.OpValue);
|
//}
|
#endregion
|
|
#region DeviceBase
|
[DeviceOperation(DeviceOpCmmd.PLCOperation, true)]
|
protected override void DeviceRun(IOperationConfig config)
|
{
|
OmronFinsOperationConfig opConfig = config as OmronFinsOperationConfig;
|
if (opConfig == null)
|
{
|
return;
|
}
|
|
int scanInterval = (int)Math.Ceiling((double)IConfig.ScanInterval / (double)opConfig.Items.Count);
|
|
List<PLC_ITEM> items = opConfig.Items.Where(item => !string.IsNullOrWhiteSpace(item.ADDRESS)).ToList();
|
//do
|
//{
|
// items.ForEach(item =>
|
// {
|
// if ((item.OP_TYPE & (int)EnumHelper.PLCOpType.Read) == (int)EnumHelper.PLCOpType.Read)
|
// {
|
// ReadItem(item);
|
// }
|
|
// if ((item.OP_TYPE & (int)EnumHelper.PLCOpType.Write) == (int)EnumHelper.PLCOpType.Write)
|
// {
|
// WriteItem(item);
|
// }
|
|
// Thread.Sleep(scanInterval);
|
// });
|
|
// if (CurrentState != EnumHelper.DeviceState.DSOpen)
|
// {
|
// break;
|
// }
|
//} while (opConfig.IsCycle);
|
|
if (opConfig.IsCycle)
|
{
|
while (CurrentState == EnumHelper.DeviceState.DSOpen)
|
{
|
InitialScanClient();
|
|
items.ForEach(item =>
|
{
|
if ((item.OP_TYPE & (int)EnumHelper.PLCOpType.Read) == (int)EnumHelper.PLCOpType.Read)
|
{
|
ReadItem(item);
|
}
|
|
if ((item.OP_TYPE & (int)EnumHelper.PLCOpType.Write) == (int)EnumHelper.PLCOpType.Write)
|
{
|
WriteItem(item);
|
}
|
|
Thread.Sleep(scanInterval);
|
});
|
}
|
}
|
else
|
{
|
InitialOpClient();
|
|
items.ForEach(item =>
|
{
|
if ((item.OP_TYPE & (int)EnumHelper.PLCOpType.Read) == (int)EnumHelper.PLCOpType.Read)
|
{
|
ReadItem(item);
|
}
|
|
if ((item.OP_TYPE & (int)EnumHelper.PLCOpType.Write) == (int)EnumHelper.PLCOpType.Write)
|
{
|
WriteItem(item);
|
}
|
|
//Thread.Sleep(scanInterval);
|
});
|
}
|
}
|
|
protected override void DeviceSet(IDeviceConfig config)
|
{
|
}
|
|
protected override void Init()
|
{
|
plcEP = new IPEndPoint(IPAddress.Parse(IConfig.PLCIpAddress), IConfig.PLCPort);
|
|
frame = new FinsFrame(IConfig.DNA, IConfig.DA1, IConfig.DA2, IConfig.SNA, IConfig.SA1, IConfig.SA2, false);
|
|
oldValues = new List<int>();
|
}
|
|
protected override void Pause()
|
{
|
}
|
|
protected override void Resume()
|
{
|
}
|
|
protected override void Start()
|
{
|
scanBuffer = null;
|
|
InitialOpClient();
|
InitialScanClient();
|
|
Task.Run(() =>
|
{
|
Monitor();
|
});
|
}
|
|
protected override void Stop()
|
{
|
try
|
{
|
scanClient.Close();
|
opClient.Close();
|
|
scanClient = null;
|
opClient = null;
|
}
|
catch (Exception)
|
{
|
}
|
}
|
#endregion
|
|
public OmronFinsInitialConfig IConfig
|
{
|
get
|
{
|
return InitialConfig as OmronFinsInitialConfig;
|
}
|
}
|
|
FinsFrame frame = null;
|
|
static object opClientLock = new object();
|
|
TcpClient scanClient = new TcpClient();
|
TcpClient opClient = new TcpClient();
|
|
NetworkStream scanStream = null;
|
NetworkStream opStream = null;
|
|
IPEndPoint plcEP;
|
|
private int currentSid = 1;
|
public int CurrentSid
|
{
|
get
|
{
|
if (currentSid > 1000)
|
{
|
currentSid = 1;
|
}
|
|
return currentSid++;
|
}
|
}
|
|
//private void InitialClient(TcpClient client)
|
//{
|
// if (client == null || !client.Connected)
|
// {
|
// //client?.Close();
|
// client = new TcpClient();
|
// client.NoDelay = true;
|
// client.Client.Blocking = true;
|
// client.SendBufferSize = 0;
|
// client.ReceiveBufferSize = 0;
|
// client.Connect(plcEP);
|
// }
|
//}
|
|
private void InitialScanClient()
|
{
|
if (scanClient == null || !scanClient.Connected)
|
{
|
//client?.Close();
|
scanClient = new TcpClient();
|
scanClient.NoDelay = true;
|
scanClient.Client.Blocking = true;
|
scanClient.SendBufferSize = 0;
|
scanClient.ReceiveBufferSize = 0;
|
scanClient.Connect(plcEP);
|
|
byte[] dataRequest = frame.GetTcpRequestFrame(1);
|
scanStream = scanClient.GetStream();
|
scanStream.Write(dataRequest, 0, dataRequest.Length);
|
byte[] dataRead = new byte[2048];
|
scanStream.Read(dataRead, 0, dataRead.Length);
|
}
|
}
|
|
private void InitialOpClient()
|
{
|
if (opClient == null || !opClient.Connected)
|
{
|
opClient = new TcpClient();
|
opClient.SendBufferSize = opClient.ReceiveBufferSize = 0;
|
opClient.NoDelay = true;
|
opClient.Client.Blocking = true;
|
opClient.Connect(plcEP);
|
|
byte[] dataRequest = frame.GetTcpRequestFrame(2);
|
opStream = opClient.GetStream();
|
opStream.Write(dataRequest, 0, dataRequest.Length);
|
byte[] dataRead = new byte[2048];
|
opStream.Read(dataRead, 0, dataRead.Length);
|
}
|
}
|
|
[DeviceOperation(DeviceOpCmmd.PLCRead, true)]
|
public List<int> Read(IOperationConfig config)
|
{
|
OmronFinsOperationConfig opConfig = config as OmronFinsOperationConfig;
|
return Read(opConfig.StartAddress, opConfig.OpLength);
|
}
|
|
public List<int> Read(int startAddress, int length)
|
{
|
List<int> monitorValues = new List<int>();
|
|
PLC_ITEM item = new PLC_ITEM();
|
item.ADDRESS = "D" + startAddress;
|
item.OP_TYPE = 1;
|
item.ITEM_LENGTH = length;
|
|
var data = frame.GetSendReadFrameBytes(item, CurrentSid);
|
opStream.Write(data, 0, data.Length);
|
|
byte[] buffer = new byte[2048];
|
int readSize = opStream.Read(buffer, 0, buffer.Length);
|
|
if (readSize > 0)
|
{
|
List<int> values = frame.AnalyseReceivedItems(buffer.Take(readSize).ToArray(), item);
|
return values;
|
}
|
else
|
{
|
return null;
|
}
|
}
|
|
#region IMonitor
|
byte[] scanBuffer = null;
|
public override List<int> GetMonitorValues(int startAddress, int length)
|
{
|
InitialScanClient();
|
|
List<int> monitorValues = new List<int>();
|
|
PLC_ITEM item = new PLC_ITEM();
|
item.ADDRESS = "D" + startAddress;
|
item.OP_TYPE = 1;
|
item.ITEM_LENGTH = length;
|
|
if (scanBuffer == null)
|
{
|
scanBuffer = frame.GetSendReadFrameBytes(item, CurrentSid);
|
}
|
|
scanStream.Write(scanBuffer, 0, scanBuffer.Length);
|
|
byte[] buffer = new byte[2048];
|
int readSize = scanStream.Read(buffer, 0, buffer.Length);
|
|
if (readSize > 0)
|
{
|
List<int> values = frame.AnalyseReceivedItems(buffer.Take(readSize).ToArray(), item);
|
return values;
|
}
|
else
|
{
|
return new List<int>();
|
}
|
}
|
#endregion
|
|
#region Log
|
object logLock = new object();
|
private async void LogAsync(DateTime dt, string info)
|
{
|
await Task.Run(() =>
|
{
|
if (IConfig.IsEnabelLog)
|
{
|
lock (logLock)
|
{
|
DirectoryInfo dir = new DirectoryInfo(IConfig.LogPath);
|
if (!dir.Exists)
|
{
|
dir.Create();
|
}
|
|
string filePath = Path.Combine(IConfig.LogPath, "PLC_" + DateTime.Now.ToString("yyyyMMdd") + ".txt");
|
|
using (StreamWriter writer = new StreamWriter(filePath, true))
|
{
|
writer.WriteLine(dt.ToString("HH:mm:ss.fff"));
|
writer.WriteLine(info);
|
writer.WriteLine();
|
|
writer.Flush();
|
writer.Close();
|
}
|
}
|
}
|
});
|
}
|
|
//private async void LogAsync(DateTime dt, IModbusFrame frame)
|
//{
|
// await Task.Run(() =>
|
// {
|
// if (IConfig.IsEnabelLog)
|
// {
|
// lock (logLock)
|
// {
|
// DirectoryInfo dir = new DirectoryInfo(IConfig.LogPath);
|
// if (!dir.Exists)
|
// {
|
// dir.Create();
|
// }
|
|
// string filePath = Path.Combine(IConfig.LogPath, "PLC_" + DateTime.Now.ToString("yyyyMMdd") + ".txt");
|
|
// using (StreamWriter writer = new StreamWriter(filePath, true))
|
// {
|
// writer.WriteLine(dt.ToString("HH:mm:ss.fff"));
|
// writer.WriteLine(frame.GetFrameString());
|
// writer.WriteLine();
|
|
// writer.Flush();
|
// writer.Close();
|
// }
|
// }
|
// }
|
// });
|
//}
|
#endregion
|
}
|
}
|