using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Event; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.Util; using MECF.Framework.RT.Core.IoProviders; using MECF.Framework.RT.Core.IoProviders.Mitsubishis; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Xml; namespace athosRT.Devices { public class SuperMCProtocolPLC : IoProvider { private string _ip = "127.0.0.1"; private string _localIp = "127.0.0.1"; private int _port = 6731; private int _socketId = 101; private int _stationId = 102; private byte[] _bufferIn; private byte[] _bufferOut; private MCProtocol.MC_COMMAND_HEADER _header; private MCProtocol.MC_BATCH_COMMAND _batchCommand; private MCSocket _socket; private int demandAiFrom; private int demandAiSize; private int demandAoFrom; private int demandAoSize; private bool inDemanding = false; private string aiStoragename = "R"; private string aoStoragename = "R"; private string diStoragename = "M"; private string doStoragename = "M"; private int perIoLength = 960; private int diStartOffset = 0; private int doStartOffset = 0; private int aiStartOffset = 0; private int aoStartOffset = 0; private Stopwatch stopwatchDi = new Stopwatch(); private Stopwatch stopwatchDo = new Stopwatch(); private Stopwatch stopwatchAi = new Stopwatch(); private Stopwatch stopwatchAo = new Stopwatch(); private int comunicationSpanDi; private int comunicationSpanDo; private int comunicationSpanAi; private int comunicationSpanAo; protected int comunicationSpanTotal; private Stopwatch stopwatchTotal = new Stopwatch(); private List _blockSectionsDemand; public override void Initialize( string module, string name, List lstBuffers, IIoBuffer buffer, XmlElement nodeParameter, Dictionary ioMappingPathFile) { this.Module = module; this.Name = name; this._source = module + "." + name; this._buffer = buffer; this._nodeParameter = nodeParameter; this._blockSections = lstBuffers; buffer.SetBufferBlock(this._source, lstBuffers); buffer.SetIoMap(this._source, ioMappingPathFile); this.SetParameter(nodeParameter); this.State = IoProviderStateEnum.Uninitialized; this._thread = new PeriodicJob(50, OnTimer, name); } protected override bool OnTimer() { if (this.State == IoProviderStateEnum.Uninitialized) { this.SetState(IoProviderStateEnum.Opening); this.Open(); } if (this.State == IoProviderStateEnum.Opened) { try { this.stopwatchTotal.Start(); foreach (IoBlockItem blockSection in this._blockSections) { if (blockSection.Type == IoType.DI) { this.stopwatchDi.Start(); bool[] buffer = this.ReadDi(blockSection.Offset, (int) blockSection.Size); if (buffer != null) this._buffer.SetDiBuffer(this._source, blockSection.Offset, buffer); this.stopwatchDi.Stop(); } else if (blockSection.Type == IoType.AI) { this.stopwatchAi.Start(); if (this.inDemanding) { short[] buffer = this.ReadAi(blockSection.Offset, (int) blockSection.Size); if (buffer != null) this._buffer.SetAiBuffer(this._source, blockSection.Offset, buffer); } else if (this._blockSectionsDemand != null) { IoBlockItem ioBlockItem = this._blockSectionsDemand.Find((Predicate) (x => x.Type == IoType.AI)); if (ioBlockItem != null && this.demandAiSize > 0) { short[] buffer = this.ReadAi(ioBlockItem.Offset, (int) ioBlockItem.Size); if (buffer != null) this._buffer.SetAiBuffer(this._source, this.demandAiFrom, buffer, this.demandAiSize); } } else { short[] buffer = this.ReadAi(blockSection.Offset, (int) blockSection.Size); if (buffer != null) this._buffer.SetAiBuffer(this._source, blockSection.Offset, buffer); } this.stopwatchAi.Stop(); } } this.comunicationSpanDi = (int) this.stopwatchDi.ElapsedMilliseconds; this.stopwatchDi.Reset(); this.comunicationSpanAi = (int) this.stopwatchAi.ElapsedMilliseconds; this.stopwatchAi.Reset(); this.stopwatchAo.Start(); Dictionary aoBuffer = this._buffer.GetAoBuffer(this._source); if (aoBuffer != null) { if (this.inDemanding) { if (this.demandAoSize > 0) { foreach (KeyValuePair keyValuePair in aoBuffer) this.WriteAo(keyValuePair.Key, keyValuePair.Value); } } else { foreach (KeyValuePair keyValuePair in aoBuffer) { if (keyValuePair.Key == this.demandAoFrom) { short[] numArray = new short[keyValuePair.Value.Length - this.demandAoSize]; Array.Copy((Array) keyValuePair.Value, this.demandAoSize, (Array) numArray, 0, numArray.Length); this.WriteAo(this.demandAoFrom + this.demandAoSize, numArray); } else this.WriteAo(keyValuePair.Key, keyValuePair.Value); } } } this.stopwatchAo.Stop(); this.comunicationSpanAo = (int) this.stopwatchAo.ElapsedMilliseconds; this.stopwatchAo.Reset(); this.stopwatchDo.Start(); Dictionary doBuffer = this._buffer.GetDoBuffer(this._source); if (doBuffer != null) { foreach (KeyValuePair keyValuePair in doBuffer) this.WriteDo(keyValuePair.Key, keyValuePair.Value); } this.stopwatchDo.Stop(); this.comunicationSpanDo = (int) this.stopwatchDo.ElapsedMilliseconds; this.stopwatchDo.Reset(); this.stopwatchTotal.Stop(); this.comunicationSpanTotal = (int) this.stopwatchTotal.ElapsedMilliseconds; this.stopwatchTotal.Reset(); } catch (Exception ex) { LOG.Write(string.Format("{0} {1}", (object) this.Name, (object) ex), file: "D:\\sorter\\trunk\\Efem\\Jet\\Jet_001_2P_Jet\\EfemRT\\Devices\\SuperMCProtocalPLC.cs", member: nameof (OnTimer), line: 285); Thread.Sleep(1000);//原本就有 this.Close(); this.Open(); } } this._trigError.CLK = this.State == IoProviderStateEnum.Error; if (this._trigError.Q) EV.PostMessage(this.Module, EventEnum.DefaultAlarm, (object) string.Format("{0} error", (object) this._source)); return true; } protected override void SetParameter(XmlElement nodeParameter) { string attribute1 = nodeParameter.GetAttribute("ip"); this._localIp = nodeParameter.GetAttribute("localIp"); string attribute2 = nodeParameter.GetAttribute("port"); string attribute3 = nodeParameter.GetAttribute("network_id"); string attribute4 = nodeParameter.GetAttribute("station_id"); this.aiStoragename = nodeParameter.GetAttribute("aiStoragename"); this.aoStoragename = nodeParameter.GetAttribute("aoStoragename"); this.diStoragename = nodeParameter.GetAttribute("diStoragename"); this.doStoragename = nodeParameter.GetAttribute("doStoragename"); int.TryParse(nodeParameter.GetAttribute("perIoLength"), out this.perIoLength); this.perIoLength = this.perIoLength == 0 ? 960 : this.perIoLength; int.TryParse(nodeParameter.GetAttribute("demandAiFrom"), out this.demandAiFrom); int.TryParse(nodeParameter.GetAttribute("demandAiSize"), out this.demandAiSize); int.TryParse(nodeParameter.GetAttribute("demandAoFrom"), out this.demandAoFrom); int.TryParse(nodeParameter.GetAttribute("demandAoSize"), out this.demandAoSize); if (nodeParameter.HasAttribute("diStartOffset")) int.TryParse(nodeParameter.GetAttribute("diStartOffset"), out this.diStartOffset); if (nodeParameter.HasAttribute("doStartOffset")) int.TryParse(nodeParameter.GetAttribute("doStartOffset"), out this.doStartOffset); this._port = int.Parse(attribute2); this._ip = attribute1; this._socketId = int.Parse(attribute3); this._stationId = int.Parse(attribute4); DATA.Subscribe(this.Name + ".CommunicationStatus", (Func) (() => (this._socket == null ? 0 : (this._socket.Connected ? 1 : 0))), SubscriptionAttribute.FLAG.SaveDB); OP.Subscribe(this.Name + ".Reconnect", (Func) ((cmd, args) => { this.Close(); this.Open(); return true; })); } protected override void Open() { this._socket = new MCSocket(); this._header = new MCProtocol.MC_COMMAND_HEADER() { ProtocolID = (ushort) 80, NetworkID = (byte) this._socketId, StationID = (byte) this._stationId, RequestIONumber = (ushort) 1023, RequestStationNumber = (byte) 0, RequestDataLen = (ushort) 0, CPUMonitorTimer = (ushort) ((uint) MCProtocol.MC_CPU_MONITOR_TIMER * 2U) }; this._batchCommand = new MCProtocol.MC_BATCH_COMMAND() { Command = (ushort) 1025, DeviceCode = (byte) 168, DevicePoints = (ushort) 0, HeadAddr = (ushort) 0, Reserved = (byte) 0, SubCommand = (ushort) 0 }; this._bufferOut = new byte[2048]; this._bufferIn = new byte[2048]; this._socket.Open(this._ip, this._port, this._localIp); this.SetState(IoProviderStateEnum.Opened); } protected override void Close() { this._socket.Close(); this.SetState(IoProviderStateEnum.Closed); } protected override bool[] ReadDi(int _offset, int size) { int offset = _offset + this.diStartOffset; bool[] destinationArray = new bool[size]; int num = size / this.perIoLength; if (num < 1) { bool[] sourceArray = this.DoReadDi(offset, size); if (sourceArray != null) Array.Copy((Array) sourceArray, 0, (Array) destinationArray, 0, sourceArray.Length); } else { for (int index = 0; index < num; ++index) { bool[] sourceArray = this.DoReadDi(index * this.perIoLength + offset, this.perIoLength); if (sourceArray != null) Array.Copy((Array) sourceArray, 0, (Array) destinationArray, index * this.perIoLength, sourceArray.Length); } if (size % this.perIoLength != 0) { bool[] sourceArray = this.DoReadDi(offset + this.perIoLength * num, size % this.perIoLength); if (sourceArray != null) Array.Copy((Array) sourceArray, 0, (Array) destinationArray, size - size % this.perIoLength, sourceArray.Length); } } return destinationArray; } public bool SetDemandReadWrite() { this.inDemanding = true; Thread.Sleep(500);//原本就有 this.inDemanding = false; return true; } protected override short[] ReadAi(int offset, int size) { short[] destinationArray = new short[size]; int num = size / this.perIoLength; if (num < 1) { short[] sourceArray = this.DoReadAi(offset, size); if (sourceArray != null) Array.Copy((Array) sourceArray, 0, (Array) destinationArray, 0, sourceArray.Length); } else { for (int index = 0; index < num; ++index) { short[] sourceArray = this.DoReadAi(index * this.perIoLength + offset, this.perIoLength); if (sourceArray != null) Array.Copy((Array) sourceArray, 0, (Array) destinationArray, index * this.perIoLength, sourceArray.Length); } if (size % this.perIoLength != 0) { short[] sourceArray = this.DoReadAi(offset + this.perIoLength * num, size % this.perIoLength); if (sourceArray != null) Array.Copy((Array) sourceArray, 0, (Array) destinationArray, size - size % this.perIoLength, sourceArray.Length); } } return destinationArray; } protected override void WriteDo(int _offset, bool[] data) { int offset = _offset + this.doStartOffset; bool[] array = new bool[this.perIoLength]; int num = data.Length / this.perIoLength; if (num < 1) { Array.Copy((Array) data, 0, (Array) array, 0, data.Length); Array.Resize(ref array, data.Length); this.DoWriteDo(offset, array); } else { for (int index = 0; index < num; ++index) { Array.Copy((Array) data, index * this.perIoLength, (Array) array, 0, array.Length); this.DoWriteDo(offset + this.perIoLength * index, array); } if (data.Length % this.perIoLength != 0) { Array.Copy((Array) data, this.perIoLength * num, (Array) array, 0, data.Length % this.perIoLength); Array.Resize(ref array, data.Length % this.perIoLength); this.DoWriteDo(offset + this.perIoLength * num, array); } } } protected override void WriteAo(int offset, short[] data) { short[] array = new short[this.perIoLength]; int num = data.Length / this.perIoLength; if (num < 1) { Array.Copy((Array) data, 0, (Array) array, 0, data.Length); Array.Resize(ref array, data.Length); this.DoWriteAo(offset, array); } else { for (int count = 0; count < num; ++count) { Array.Copy((Array) data, count * this.perIoLength, (Array) array, 0, array.Length); this.DoWriteAo(offset + this.perIoLength * count, array, data.Length, count); } if (data.Length % this.perIoLength != 0) { Array.Copy((Array) data, this.perIoLength * num, (Array) array, 0, data.Length % this.perIoLength); Array.Resize(ref array, data.Length % this.perIoLength); this.DoWriteAo(offset + this.perIoLength * num, array, data.Length); } } } private bool WriteData(byte[] data, int length) => this._socket.Write(data, length); private int ReceiveData(byte[] data) => this._socket.Read(data); private short[] DoReadAi(int offset, int size) { this._batchCommand.DeviceCode = (byte) MelsecElement.ChooseMelsecElement(this.aiStoragename).m_nBinCode; this._batchCommand.Command = (ushort) 1025; this._batchCommand.SubCommand = (ushort) 0; this._batchCommand.HeadAddr = (ushort) (offset & (int) ushort.MaxValue); this._batchCommand.Reserved = (byte) (offset >> 16); this._batchCommand.DevicePoints = (ushort) size; this._header.RequestDataLen = (ushort) (MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE); byte[] sourceArray1 = MCProtocol.Struct2Bytes((object) this._header); byte[] sourceArray2 = MCProtocol.Struct2Bytes((object) this._batchCommand); Array.Copy((Array) sourceArray1, 0, (Array) this._bufferOut, 0, sourceArray1.Length); Array.Copy((Array) sourceArray2, 0, (Array) this._bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, sourceArray2.Length); if (!this.WriteData(this._bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE)) return (short[]) null; int length = this.ReceiveData(this._bufferIn) - MCProtocol.MC_QHEADER_RESPONSE_SIZE; if (length < 0) return (short[]) null; MCProtocol.MC_RESPONSE_HEADER mcResponseHeader = MCProtocol.ToStruct(this._bufferIn); if (mcResponseHeader.ProtocolId != (ushort) 208 && mcResponseHeader.CompleteCode > (ushort) 0) return (short[]) null; short[] numArray = new short[size]; byte[] destinationArray = new byte[length]; Array.Copy((Array) this._bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE, (Array) destinationArray, 0, destinationArray.Length); int index1 = 0; for (int index2 = 0; index1 < numArray.Length & index2 < destinationArray.Length; index2 += 2) { numArray[index1] = (short) BitConverter.ToUInt16(destinationArray, index1 * 2); ++index1; } return numArray; } private void DoWriteAo(int offset, short[] data, int total = 0, int count = 100) { ushort[] numArray = new ushort[data.Length]; ushort[] array = ((IEnumerable) data).Select((Func) (x => (ushort) x)).ToArray(); this._batchCommand.DeviceCode = (byte) MelsecElement.ChooseMelsecElement(this.aoStoragename).m_nBinCode; this._batchCommand.Command = (ushort) 5121; this._batchCommand.SubCommand = (ushort) 0; this._batchCommand.HeadAddr = (ushort) (offset & (int) ushort.MaxValue); this._batchCommand.Reserved = (byte) (offset >> 16); this._batchCommand.DevicePoints = (ushort) data.Length; this._header.RequestDataLen = (ushort) (MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE + MCProtocol.ShortSize * data.Length); byte[] sourceArray1 = MCProtocol.Struct2Bytes((object) this._header); byte[] sourceArray2 = MCProtocol.Struct2Bytes((object) this._batchCommand); byte[] sourceArray3 = MCProtocol.Ushort2Byte(array); Array.Copy((Array) sourceArray1, 0, (Array) this._bufferOut, 0, sourceArray1.Length); Array.Copy((Array) sourceArray2, 0, (Array) this._bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, sourceArray2.Length); Array.Copy((Array) sourceArray3, 0, (Array) this._bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE, sourceArray3.Length); if (!this.WriteData(this._bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.ShortSize * data.Length) || this.ReceiveData(this._bufferIn) <= 0) return; MCProtocol.MC_RESPONSE_HEADER mcResponseHeader = MCProtocol.ToStruct(this._bufferIn); if (mcResponseHeader.ProtocolId == (ushort) 208 || mcResponseHeader.CompleteCode <= (ushort) 0) return; LOG.Write(" failed with code," + mcResponseHeader.CompleteCode.ToString(), file: "D:\\sorter\\trunk\\Efem\\Jet\\Jet_001_2P_Jet\\EfemRT\\Devices\\SuperMCProtocalPLC.cs", member: nameof (DoWriteAo), line: 619); } private bool[] DoReadDi(int offset, int size) { this._batchCommand.DeviceCode = (byte) MelsecElement.ChooseMelsecElement(this.diStoragename).m_nBinCode; this._batchCommand.Command = (ushort) 1025; this._batchCommand.SubCommand = (ushort) 0; this._batchCommand.HeadAddr = (ushort) (offset & (int) ushort.MaxValue); this._batchCommand.Reserved = (byte) (offset >> 16); this._batchCommand.DevicePoints = size % 16 > 0 ? (ushort) (size / 16 + 1) : (ushort) (size / 16); this._header.RequestDataLen = (ushort) (MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE); byte[] sourceArray1 = MCProtocol.Struct2Bytes((object) this._header); byte[] sourceArray2 = MCProtocol.Struct2Bytes((object) this._batchCommand); Array.Copy((Array) sourceArray1, 0, (Array) this._bufferOut, 0, sourceArray1.Length); Array.Copy((Array) sourceArray2, 0, (Array) this._bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, sourceArray2.Length); if (!this.WriteData(this._bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE)) return (bool[]) null; int length = this.ReceiveData(this._bufferIn) - MCProtocol.MC_QHEADER_RESPONSE_SIZE; if (length < 0) return (bool[]) null; MCProtocol.MC_RESPONSE_HEADER mcResponseHeader = MCProtocol.ToStruct(this._bufferIn); if (mcResponseHeader.ProtocolId != (ushort) 208 && mcResponseHeader.CompleteCode > (ushort) 0) return (bool[]) null; bool[] source = new bool[length * 8]; byte[] numArray = new byte[length]; Array.Copy((Array) this._bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE, (Array) numArray, 0, numArray.Length); BitArray bitArray = new BitArray(numArray); for (int index = 0; index < source.Length; ++index) source[index] = bitArray.Get(index); return ((IEnumerable) source).Select((Func) (x => x)).Take(size).ToArray(); } private void DoWriteDo(int offset, bool[] data) { this._batchCommand.DeviceCode = (byte) MelsecElement.ChooseMelsecElement(this.doStoragename).m_nBinCode; this._batchCommand.Command = (ushort) 5121; this._batchCommand.SubCommand = (ushort) 0; this._batchCommand.HeadAddr = (ushort) (offset & (int) ushort.MaxValue); this._batchCommand.Reserved = (byte) (offset >> 16); this._batchCommand.DevicePoints = data.Length % 16 > 0 ? (ushort) (data.Length / 16 + 1) : (ushort) (data.Length / 16); this._header.RequestDataLen = (ushort) (MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE + (int) this._batchCommand.DevicePoints * 2); byte[] sourceArray1 = new byte[(int) this._batchCommand.DevicePoints * 2]; int index1 = 0; for (int index2 = 0; index1 < data.Length & index2 < sourceArray1.Length; ++index2) { sourceArray1[index2] += data[index1] ? (byte) 1 : (byte) 0; sourceArray1[index2] += index1 + 1 >= data.Length || !data[index1 + 1] ? (byte) 0 : (byte) 2; sourceArray1[index2] += index1 + 2 >= data.Length || !data[index1 + 2] ? (byte) 0 : (byte) 4; sourceArray1[index2] += index1 + 3 >= data.Length || !data[index1 + 3] ? (byte) 0 : (byte) 8; sourceArray1[index2] += index1 + 4 >= data.Length || !data[index1 + 4] ? (byte) 0 : (byte) 16; sourceArray1[index2] += index1 + 5 >= data.Length || !data[index1 + 5] ? (byte) 0 : (byte) 32; sourceArray1[index2] += index1 + 6 >= data.Length || !data[index1 + 6] ? (byte) 0 : (byte) 64; sourceArray1[index2] += index1 + 7 >= data.Length || !data[index1 + 7] ? (byte) 0 : (byte) 128; index1 += 8; } byte[] sourceArray2 = MCProtocol.Struct2Bytes((object) this._header); byte[] sourceArray3 = MCProtocol.Struct2Bytes((object) this._batchCommand); Array.Copy((Array) sourceArray2, 0, (Array) this._bufferOut, 0, sourceArray2.Length); Array.Copy((Array) sourceArray3, 0, (Array) this._bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, sourceArray3.Length); Array.Copy((Array) sourceArray1, 0, (Array) this._bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE, sourceArray1.Length); if (!this.WriteData(this._bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE + sourceArray1.Length) || this.ReceiveData(this._bufferIn) <= 0) return; MCProtocol.MC_RESPONSE_HEADER mcResponseHeader = MCProtocol.ToStruct(this._bufferIn); if (mcResponseHeader.CompleteCode <= (ushort) 0) return; LOG.Write("Write PLC failed with code," + mcResponseHeader.CompleteCode.ToString(), file: "D:\\sorter\\trunk\\Efem\\Jet\\Jet_001_2P_Jet\\EfemRT\\Devices\\SuperMCProtocalPLC.cs", member: nameof (DoWriteDo), line: 728); } } }