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 = opFrame.GetSendReadFrameBytes(item, CurrentSid); var stream = opClient.GetStream(); stream.Write(data, 0, data.Length); byte[] buffer = new byte[2048]; int readSize = stream.Read(buffer, 0, buffer.Length); if (readSize > 0) { List list = opFrame.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 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(); NetworkStream stream = null; lock (opClientLock) { do { try { InitialOpClient(); byte[] data = opFrame.GetSendWriteFrameBytes(item, CurrentSid); stream = opClient.GetStream(); stream.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 = stream.Read(buffer, 0, buffer.Length); if (bufferCount > 0) { opFrame.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 = stream.Read(buffer, 0, buffer.Length); if (bufferCount > 0) { opFrame.AnalyseReceivedItems(buffer.Take(bufferCount).ToArray(), item); } } catch (Exception ex) { LogAsync(DateTime.Now, "写入反馈异常\r\n" + ex.GetExceptionMessage()); } }); } } //item.ITEM_VALUE = string.Join(",", receiveFrame.BodyFrame.OpValue); } /// /// 写单独地址 /// /// 10进制表示的地址,首位表示类型 例如 45000 /// /// 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 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); scanFrame = new FinsFrame(IConfig.DNA, 0, IConfig.DA2, IConfig.SNA, 0, IConfig.SA2, false); opFrame = new FinsFrame(IConfig.DNA, 0, IConfig.DA2, IConfig.SNA, 0, IConfig.SA2, false); oldValues = new List(); } 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 scanFrame = null; FinsFrame opFrame = null; static object opClientLock = new object(); TcpClient scanClient = new TcpClient(); TcpClient opClient = new TcpClient(); 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); // } //} byte serverNode = 0; byte scanNode = 0; byte opNode = 0; 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.ReceiveTimeout = scanClient.SendTimeout = 5000; scanClient.Connect(plcEP); scanFrame = new FinsFrame(IConfig.DNA, serverNode, IConfig.DA2, IConfig.SNA, scanNode, IConfig.SA2, false); byte[] dataRequest = scanFrame.GetTcpRequestFrame(0); var stream = scanClient.GetStream(); stream.Write(dataRequest, 0, dataRequest.Length); byte[] dataRead = new byte[2048]; int readSize = stream.Read(dataRead, 0, dataRead.Length); if (readSize <= 0) { throw new ProcessException("PLC通信握手信号返回不可为空"); } if (dataRead[15] != 0) { throw new ProcessException($"PLC通信握手信号返回异常:{dataRead[15]}"); } serverNode = dataRead[23]; scanNode = dataRead[19]; scanFrame = new FinsFrame(IConfig.DNA, serverNode, IConfig.DA2, IConfig.SNA, scanNode, IConfig.SA2, false); } } 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); opFrame = new FinsFrame(IConfig.DNA, serverNode, IConfig.DA2, IConfig.SNA, opNode, IConfig.SA2, false); byte[] dataRequest = opFrame.GetTcpRequestFrame(0); var stream = opClient.GetStream(); stream.Write(dataRequest, 0, dataRequest.Length); byte[] dataRead = new byte[2048]; int readSize = stream.Read(dataRead, 0, dataRead.Length); if (readSize <= 0) { throw new ProcessException("PLC通信握手信号返回不可为空"); } if (dataRead[15] != 0) { throw new ProcessException($"PLC通信握手信号返回异常:{dataRead[15]}"); } serverNode = dataRead[23]; opNode = dataRead[19]; opFrame = new FinsFrame(IConfig.DNA, serverNode, IConfig.DA2, IConfig.SNA, opNode, IConfig.SA2, false); } } [DeviceOperation(DeviceOpCmmd.PLCRead, true)] public List Read(IOperationConfig config) { OmronFinsOperationConfig opConfig = config as OmronFinsOperationConfig; return Read(opConfig.StartAddress, opConfig.OpLength); } public List Read(int startAddress, int length) { List monitorValues = new List(); PLC_ITEM item = new PLC_ITEM(); item.ADDRESS = "D" + startAddress; item.OP_TYPE = 1; item.ITEM_LENGTH = length; var data = opFrame.GetSendReadFrameBytes(item, CurrentSid); var stream = opClient.GetStream(); stream.Write(data, 0, data.Length); byte[] buffer = new byte[2048]; int readSize = stream.Read(buffer, 0, buffer.Length); if (readSize > 0) { List values = opFrame.AnalyseReceivedItems(buffer.Take(readSize).ToArray(), item); return values; } else { return null; } } #region IMonitor byte[] scanBuffer = null; public override List GetMonitorValues(int startAddress, int length) { InitialScanClient(); List monitorValues = new List(); PLC_ITEM item = new PLC_ITEM(); item.ADDRESS = "D" + startAddress; item.OP_TYPE = 1; item.ITEM_LENGTH = length; if (scanBuffer == null) { scanBuffer = scanFrame.GetSendReadFrameBytes(item, CurrentSid); } var stream = scanClient.GetStream(); stream.Write(scanBuffer, 0, scanBuffer.Length); byte[] buffer = new byte[2048]; int readSize = stream.Read(buffer, 0, buffer.Length); if (readSize > 0) { List values = scanFrame.AnalyseReceivedItems(buffer.Take(readSize).ToArray(), item); return values; } else { return new List(); } } #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 } }