using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Event; using Aitex.Core.RT.IOCore; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Communications; 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.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; namespace FurnaceRT.Equipments.Systems { public class MCProtocolPlc : IoProvider, IConnection { public string Address { get { return $"{_ip}:{_port}"; } } public bool IsConnected { get { return IsOpened; } } public bool Connect() { return true; } public bool Disconnect() { return true; } private bool _isPlcConnected; public bool IsPlcConnected { get => _isPlcConnected; set { _isPlcConnected = value; } } 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_RESPONSE_HEADER _response; private MCProtocol.MC_BATCH_COMMAND _batchCommand; private MCSocket _socket; //private int demandAiFrom; //should be the same the offset in lstBuffers //private int demandAiSize; //private int demandAoFrom; //should be the same the offset in lstBuffers //private int demandAoSize; //private bool inDemanding = false; private string _aiStoragename = "R"; private string _aoStoragename = "R"; private string _diStoragename = "B"; private string _doStoragename = "B"; private int perIoLength = 960; private bool _readDiByAi = false; private bool _writeDoByAo = false; 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 R_TRIG _trigReadDoAndAo = new R_TRIG(); private int diStartAddress; private int doStartAddress; private int aiStartAddress; private int aoStartAddress; //private List _blockSectionsDemand; public override void Initialize(string module, string name, List lstBuffers, IIoBuffer buffer, XmlElement nodeParameter, Dictionary ioMappingPathFile) { Module = module; Name = name; _source = module + "." + name; _buffer = buffer; _nodeParameter = nodeParameter; SetParameter(nodeParameter); _blockSections = lstBuffers; buffer.SetBufferBlock(_source, lstBuffers); buffer.SetIoMap(_source, ioMappingPathFile); int.TryParse(IO.GetDoList(_source)[0].Addr.Substring(1), out doStartAddress); int.TryParse(IO.GetDiList(_source)[0].Addr.Substring(1), out diStartAddress); int.TryParse(IO.GetAoList(_source)[0].Addr.Substring(1), out aoStartAddress); int.TryParse(IO.GetAiList(_source)[0].Addr.Substring(1), out aiStartAddress); State = IoProviderStateEnum.Uninitialized; _thread = new PeriodicJob(30, OnTimer, name); ConnectionManager.Instance.Subscribe(Name, this); DATA.Subscribe($"{Module}.{Name}.IsConnected", () => _socket == null ? false : _socket.Connected); OP.Subscribe($"{Name}.Reconnect", (string cmd, object[] args) => { Close(); Open(); return true; }); } public override void Reset() { _trigError.RST = true; _trigReadDoAndAo.RST = true; _trigNotConnected.RST = true; //if(!_plc.CheckIsConnected()) if (!IsPlcConnected) { Close(); Open(); } } protected override bool OnTimer() { if (State == IoProviderStateEnum.Uninitialized) { _trigReadDoAndAo.RST = true; SetState(IoProviderStateEnum.Opening); Open(); } if (State == IoProviderStateEnum.Opened) { try { stopwatchTotal.Start(); foreach (var bufferSection in _blockSections) { if (bufferSection.Type == IoType.DI) { stopwatchDi.Start(); bool[] diBuffer = ReadDi(bufferSection.Offset, bufferSection.Size); if (diBuffer != null) { _buffer.SetDiBuffer(_source, bufferSection.Offset, diBuffer); //TraceArray(diBuffer); } stopwatchDi.Stop(); } else if (bufferSection.Type == IoType.DO) { stopwatchDo.Start(); if (!_trigReadDoAndAo.M) { bool[] doBuffer = ReadDo(bufferSection.Offset, bufferSection.Size); if (doBuffer != null) { _buffer.SetDoBuffer(_source, bufferSection.Offset, doBuffer); //TraceArray(diBuffer); } } stopwatchDo.Stop(); } else if (bufferSection.Type == IoType.AI) { stopwatchAi.Start(); short[] aiBuffer = ReadAi(bufferSection.Offset, bufferSection.Size); if (aiBuffer != null) { _buffer.SetAiBuffer(_source, bufferSection.Offset, aiBuffer); } stopwatchAi.Stop(); } else if (bufferSection.Type == IoType.AO) { stopwatchAo.Start(); if (!_trigReadDoAndAo.M) { short[] aoBuffer = ReadAo(bufferSection.Offset, bufferSection.Size); if (aoBuffer != null) { _buffer.SetAoBuffer(_source, bufferSection.Offset, aoBuffer); } } stopwatchAo.Stop(); } } if (!_trigReadDoAndAo.M) _trigReadDoAndAo.CLK = true; comunicationSpanDi = (int)stopwatchDi.ElapsedMilliseconds; stopwatchDi.Reset(); comunicationSpanDo = (int)stopwatchDo.ElapsedMilliseconds; stopwatchDo.Reset(); comunicationSpanAi = (int)stopwatchAi.ElapsedMilliseconds; stopwatchAi.Reset(); comunicationSpanAo = (int)stopwatchAo.ElapsedMilliseconds; stopwatchAo.Reset(); stopwatchAo.Start(); Dictionary aos = _buffer.GetAoBuffer(_source); if (aos != null) { foreach (var ao in aos) { WriteAo(ao.Key, ao.Value); } } stopwatchAo.Stop(); comunicationSpanAo = (int)stopwatchAo.ElapsedMilliseconds; stopwatchAo.Reset(); stopwatchDo.Start(); Dictionary dos = _buffer.GetDoBuffer(_source); if (dos != null) { foreach (var doo in dos) { WriteDo(doo.Key, doo.Value); } } stopwatchDo.Stop(); comunicationSpanDo = (int)stopwatchDo.ElapsedMilliseconds; stopwatchDo.Reset(); stopwatchTotal.Stop(); comunicationSpanTotal = (int)stopwatchTotal.ElapsedMilliseconds; stopwatchTotal.Reset(); } catch (Exception ex) { LOG.Write($"{Name} {ex}"); //SetState(IoProviderStateEnum.Error); Thread.Sleep(1000); Close(); Open(); } } _trigError.CLK = State == IoProviderStateEnum.Error; if (_trigError.Q) { EV.PostAlarmLog(Module, $"{_source} PLC {_ip}:{_port} error"); } _trigNotConnected.CLK = State != IoProviderStateEnum.Opened; if (_trigNotConnected.T) { EV.PostInfoLog(Module, $"{_source} connected"); } if (_trigNotConnected.R) { EV.PostAlarmLog(Module, $"{_source} PLC {_ip}:{_port} not connected"); } return true; } protected override void SetParameter(XmlElement nodeParameter) { string strIp = nodeParameter.GetAttribute("ip"); //_localIp = nodeParameter.GetAttribute("localIp"); string strPort = nodeParameter.GetAttribute("port"); string networkId = nodeParameter.GetAttribute("network_id"); string stationId = nodeParameter.GetAttribute("station_id"); _aiStoragename = nodeParameter.GetAttribute("aiStoragename"); _aoStoragename = nodeParameter.GetAttribute("aoStoragename"); _diStoragename = nodeParameter.GetAttribute("diStoragename"); _doStoragename = nodeParameter.GetAttribute("doStoragename"); if (_diStoragename == "D") _readDiByAi = true; if (_doStoragename == "D") _writeDoByAo = true; int.TryParse(nodeParameter.GetAttribute("perIoLength"), out perIoLength); perIoLength = perIoLength == 0 ? 960 : perIoLength; int.TryParse(nodeParameter.GetAttribute("doStartAddress"), out doStartAddress); int.TryParse(nodeParameter.GetAttribute("diStartAddress"), out diStartAddress); int.TryParse(nodeParameter.GetAttribute("aoStartAddress"), out aoStartAddress); int.TryParse(nodeParameter.GetAttribute("aiStartAddress"), out aiStartAddress); _port = int.Parse(strPort); _ip = strIp; _socketId = int.Parse(networkId); _stationId = int.Parse(stationId); } protected override void Open() { _socket = new MCSocket(); _header = new MCProtocol.MC_COMMAND_HEADER() { ProtocolID = MCProtocol.MC_SUBHEADER_COMMAND_MESSAGE, NetworkID = (byte)_socketId, //NetworkID = (byte)0, StationID = (byte)_stationId, //StationID = (byte)0xff, RequestIONumber = MCProtocol.MC_REQUEST_MODULE_IO_NUMBER, RequestStationNumber = MCProtocol.MC_REQUEST_MODULE_STATION_NUMBER, RequestDataLen = 0, CPUMonitorTimer = (ushort)(MCProtocol.MC_CPU_MONITOR_TIMER * 2), }; _batchCommand = new MCProtocol.MC_BATCH_COMMAND() { Command = MCProtocol.MC_COMMAND_BATCH_READ, DeviceCode = MCProtocol.MC_DEVICE_CODE_DATA_REGISTER_WORD, DevicePoints = 0, HeadAddr = 0, Reserved = 0, SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS, }; _bufferOut = new byte[2048]; _bufferIn = new byte[2048]; if (_socket.Open(_ip, _port, _localIp)) { SetState(IoProviderStateEnum.Opened); _isPlcConnected = true; } } protected override void Close() { _socket.Close(); SetState(IoProviderStateEnum.Closed); } protected override bool[] ReadDi(int offset, int size) { if (!_isPlcConnected) { return null; } if (_readDiByAi) { if (_socket == null || !_socket.Connected) { State = IoProviderStateEnum.Error; return null; } bool[] buff = new bool[size]; var reasSize = size % 16 > 0 ? size / 16 + 1 : size / 16; var readBuff = ReadAiGetByte(diStartAddress, reasSize); var bitArray = new BitArray(readBuff); for (int i = 0; i < buff.Length; i++) { buff[i] = bitArray.Get(i); } return buff; } else { bool[] buff = new bool[size]; int count = size / perIoLength; if (count < 1) { bool[] dibuffer = DoReadDi(diStartAddress, size); if (dibuffer != null) Array.Copy(dibuffer, 0, buff, 0, dibuffer.Length); else return null; } else { bool[] dibuffer; for (int i = 0; i < count; i++) { dibuffer = DoReadDi(i * perIoLength + diStartAddress, perIoLength); if (dibuffer != null) Array.Copy(dibuffer, 0, buff, i * perIoLength, dibuffer.Length); else return null; } if (size % perIoLength != 0) { dibuffer = DoReadDi(diStartAddress + perIoLength * count, size % perIoLength); if (dibuffer != null) Array.Copy(dibuffer, 0, buff, size - size % perIoLength, dibuffer.Length); else return null; } } return buff; } } protected bool[] ReadDo(int offset, int size) { if (!_isPlcConnected) { return null; } if (_readDiByAi) { if (_socket == null || !_socket.Connected) { State = IoProviderStateEnum.Error; return null; } bool[] buff = new bool[size]; var reasSize = size % 16 > 0 ? size / 16 + 1 : size / 16; var readBuff = ReadAoGetByte(doStartAddress, reasSize); var bitArray = new BitArray(readBuff); for (int i = 0; i < buff.Length; i++) { buff[i] = bitArray.Get(i); } return buff; } else { bool[] buff = new bool[size]; int count = size / perIoLength; if (count < 1) { bool[] dibuffer = DoReadDo(doStartAddress, size); if (dibuffer != null) Array.Copy(dibuffer, 0, buff, 0, dibuffer.Length); else return null; } else { bool[] dibuffer; for (int i = 0; i < count; i++) { dibuffer = DoReadDo(i * perIoLength + doStartAddress, perIoLength); if (dibuffer != null) Array.Copy(dibuffer, 0, buff, i * perIoLength, dibuffer.Length); else return null; } if (size % perIoLength != 0) { dibuffer = DoReadDo(doStartAddress + perIoLength * count, size % perIoLength); if (dibuffer != null) Array.Copy(dibuffer, 0, buff, size - size % perIoLength, dibuffer.Length); else return null; } } return buff; } } protected override short[] ReadAi(int offset, int size) { if (!_isPlcConnected) { return null; } short[] buff = new short[size]; int count = size / perIoLength; if (count < 1) { short[] aibuffer = DoReadAi(aiStartAddress, size); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, 0, aibuffer.Length); } else { short[] aibuffer; for (int i = 0; i < count; i++) { aibuffer = DoReadAi(i * perIoLength + aiStartAddress, perIoLength); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, i * perIoLength, aibuffer.Length); } if (size % perIoLength != 0) { aibuffer = DoReadAi(aiStartAddress + perIoLength * count, size % perIoLength); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, size - size % perIoLength, aibuffer.Length); } } return buff; } protected short[] ReadAo(int offset, int size) { if (!_isPlcConnected) { return null; } short[] buff = new short[size]; int count = size / perIoLength; if (count < 1) { short[] aibuffer = DoReadAo(aoStartAddress, size); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, 0, aibuffer.Length); } else { short[] aibuffer; for (int i = 0; i < count; i++) { aibuffer = DoReadAo(i * perIoLength + aoStartAddress, perIoLength); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, i * perIoLength, aibuffer.Length); } if (size % perIoLength != 0) { aibuffer = DoReadAo(aoStartAddress + perIoLength * count, size % perIoLength); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, size - size % perIoLength, aibuffer.Length); } } return buff; } protected override void WriteDo(int offset, bool[] data) { if (!_isPlcConnected) { return; } if (_writeDoByAo) { byte[] byteData = new byte[data.Length % 8 > 0 ? data.Length / 8 + 1 : data.Length / 8]; for (int i = 0, byteDataIndex = 0; i < data.Length & byteDataIndex < byteData.Length; i += 8, byteDataIndex++) { byteData[byteDataIndex] += (byte)(data[i] ? 1 : 0); byteData[byteDataIndex] += (byte)(i + 1 < data.Length && data[i + 1] ? 1 << 1 : 0); byteData[byteDataIndex] += (byte)(i + 2 < data.Length && data[i + 2] ? 1 << 2 : 0); byteData[byteDataIndex] += (byte)(i + 3 < data.Length && data[i + 3] ? 1 << 3 : 0); byteData[byteDataIndex] += (byte)(i + 4 < data.Length && data[i + 4] ? 1 << 4 : 0); byteData[byteDataIndex] += (byte)(i + 5 < data.Length && data[i + 5] ? 1 << 5 : 0); byteData[byteDataIndex] += (byte)(i + 6 < data.Length && data[i + 6] ? 1 << 6 : 0); byteData[byteDataIndex] += (byte)(i + 7 < data.Length && data[i + 7] ? 1 << 7 : 0); } WriteAoByte(doStartAddress, byteData); } else { bool[] databuffer = new bool[perIoLength]; int count = data.Length / perIoLength; if (count < 1) { Array.Copy(data, 0, databuffer, 0, data.Length); Array.Resize(ref databuffer, data.Length); DoWriteDo(doStartAddress, databuffer); } else { for (int i = 0; i < count; i++) { Array.Copy(data, i * perIoLength, databuffer, 0, databuffer.Length); DoWriteDo(doStartAddress + perIoLength * i, databuffer); } if (data.Length % perIoLength != 0) { Array.Copy(data, perIoLength * count, databuffer, 0, data.Length % perIoLength); Array.Resize(ref databuffer, data.Length % perIoLength); DoWriteDo(doStartAddress + perIoLength * count, databuffer); } } } } protected override void WriteAo(int offset, short[] data) { if (!_isPlcConnected) { return; } short[] databuffer = new short[perIoLength]; int count = data.Length / perIoLength; if (count < 1) { Array.Copy(data, 0, databuffer, 0, data.Length); Array.Resize(ref databuffer, data.Length); DoWriteAo(aoStartAddress, databuffer); } else { for (int i = 0; i < count; i++) { Array.Copy(data, i * perIoLength, databuffer, 0, databuffer.Length); DoWriteAo(aoStartAddress + perIoLength * i, databuffer, data.Length, i); } if (data.Length % perIoLength != 0) { Array.Copy(data, perIoLength * count, databuffer, 0, data.Length % perIoLength); Array.Resize(ref databuffer, data.Length % perIoLength); DoWriteAo(aoStartAddress + perIoLength * count, databuffer, data.Length); } } } private byte[] ReadAiGetByte(int startAddress, int size) { byte[] buff = new byte[size * 2]; int count = size / perIoLength; if (count < 1) { byte[] aibuffer = DoReadAiGetByte(startAddress, size, _aiStoragename); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, 0, aibuffer.Length); } else { byte[] aibuffer; for (int i = 0; i < count; i++) { aibuffer = DoReadAiGetByte(i * perIoLength + startAddress, perIoLength, _aiStoragename); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, i * perIoLength, aibuffer.Length); } if (size % perIoLength != 0) { aibuffer = DoReadAiGetByte(startAddress + perIoLength * count, size % perIoLength, _aiStoragename); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, size - size % perIoLength, aibuffer.Length); } } return buff; } private byte[] ReadAoGetByte(int startAddress, int size) { byte[] buff = new byte[size * 2]; int count = size / perIoLength; if (count < 1) { byte[] aibuffer = DoReadAoGetByte(startAddress, size, _aiStoragename); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, 0, aibuffer.Length); } else { byte[] aibuffer; for (int i = 0; i < count; i++) { aibuffer = DoReadAoGetByte(i * perIoLength + startAddress, perIoLength, _aiStoragename); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, i * perIoLength, aibuffer.Length); } if (size % perIoLength != 0) { aibuffer = DoReadAoGetByte(startAddress + perIoLength * count, size % perIoLength, _aiStoragename); if (aibuffer != null) Array.Copy(aibuffer, 0, buff, size - size % perIoLength, aibuffer.Length); } } return buff; } private void WriteAoByte(int startAddress, byte[] data) { byte[] databuffer = new byte[perIoLength * 2]; int count = (data.Length / 2) / perIoLength; if (count < 1) { DoWriteAoByte(startAddress, data, _aoStoragename); } else { for (int i = 0; i < count; i++) { Array.Copy(data, i * perIoLength * 2, databuffer, 0, databuffer.Length * 2); DoWriteAoByte(startAddress + perIoLength * i, databuffer, _aoStoragename, data.Length * 2, i); } if (data.Length / 2 % perIoLength != 0) { Array.Copy(data, perIoLength * 2 * count, databuffer, 0, data.Length / 2 % perIoLength); Array.Resize(ref databuffer, data.Length / 2 % perIoLength); DoWriteAoByte(startAddress + perIoLength * count, databuffer, _aoStoragename, data.Length); } } } private void DoWriteAoByte(int offset, byte[] data, string aoStoragename, int total = 0, int count = 100) { _batchCommand.DeviceCode = (byte)MelsecElement.ChooseMelsecElement(aoStoragename).m_nBinCode; _batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_WRITE; _batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS; _batchCommand.HeadAddr = (ushort)(offset & 0xFFFF); _batchCommand.Reserved = (byte)(offset >> 16); _batchCommand.DevicePoints = (ushort)(data.Length / 2); _header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE + MCProtocol.ShortSize * data.Length / 2); byte[] header = MCProtocol.Struct2Bytes(_header); byte[] command = MCProtocol.Struct2Bytes(_batchCommand); Array.Copy(header, 0, _bufferOut, 0, header.Length); Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length); Array.Copy(data, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE, data.Length); if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.ShortSize * data.Length / 2)) { return; } if (ReceiveData(_bufferIn) <= 0) { return; } MCProtocol.MC_RESPONSE_HEADER responseHeader = MCProtocol.ToStruct(_bufferIn); if (responseHeader.ProtocolId != 0x00d0 && responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS) { LOG.Write(" failed with code," + responseHeader.CompleteCode); return; } } private byte[] DoReadAiGetByte(int offset, int size, string _aiStoragename) { _batchCommand.DeviceCode = (byte)MelsecElement.ChooseMelsecElement(_aiStoragename).m_nBinCode; _batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_READ; _batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS; _batchCommand.HeadAddr = (ushort)(offset & 0xFFFF); _batchCommand.Reserved = (byte)(offset >> 16); _batchCommand.DevicePoints = (ushort)size; _header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE); byte[] buffer = MCProtocol.Struct2Bytes(_header); byte[] command = MCProtocol.Struct2Bytes(_batchCommand); Array.Copy(buffer, 0, _bufferOut, 0, buffer.Length); Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length); if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE)) { return null; } //receiveLen < MCProtocol.MC_QHEADER_RESPONSE_SIZE means no data in bufferIn int receiveLen = ReceiveData(_bufferIn); int dataLength = receiveLen - MCProtocol.MC_QHEADER_RESPONSE_SIZE; if (dataLength < 0) { return null; } MCProtocol.MC_RESPONSE_HEADER responseHeader = MCProtocol.ToStruct(_bufferIn); if (responseHeader.ProtocolId != 0x00d0 && responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS) { return null; } byte[] dataBuff = new byte[dataLength]; Array.Copy(_bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE, dataBuff, 0, dataBuff.Length); return dataBuff; } private byte[] DoReadAoGetByte(int offset, int size, string _aiStoragename) { _batchCommand.DeviceCode = (byte)MelsecElement.ChooseMelsecElement(_aiStoragename).m_nBinCode; _batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_READ; _batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS; _batchCommand.HeadAddr = (ushort)(offset & 0xFFFF); _batchCommand.Reserved = (byte)(offset >> 16); _batchCommand.DevicePoints = (ushort)size; _header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE); byte[] buffer = MCProtocol.Struct2Bytes(_header); byte[] command = MCProtocol.Struct2Bytes(_batchCommand); Array.Copy(buffer, 0, _bufferOut, 0, buffer.Length); Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length); if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE)) { return null; } //receiveLen < MCProtocol.MC_QHEADER_RESPONSE_SIZE means no data in bufferIn int receiveLen = ReceiveData(_bufferIn); int dataLength = receiveLen - MCProtocol.MC_QHEADER_RESPONSE_SIZE; if (dataLength < 0) { return null; } MCProtocol.MC_RESPONSE_HEADER responseHeader = MCProtocol.ToStruct(_bufferIn); if (responseHeader.ProtocolId != 0x00d0 && responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS) { return null; } byte[] dataBuff = new byte[dataLength]; Array.Copy(_bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE, dataBuff, 0, dataBuff.Length); return dataBuff; } private bool WriteData(byte[] data, int length) { return _socket.Write(data, length); } private int ReceiveData(byte[] data) { return _socket.Read(data); } private short[] DoReadAi(int offset, int size) { _batchCommand.DeviceCode = (byte)MelsecElement.ChooseMelsecElement(_aiStoragename).m_nBinCode; _batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_READ; _batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS; _batchCommand.HeadAddr = (ushort)(offset & 0xFFFF); _batchCommand.Reserved = (byte)(offset >> 16); _batchCommand.DevicePoints = (ushort)size; _header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE); byte[] buffer = MCProtocol.Struct2Bytes(_header); byte[] command = MCProtocol.Struct2Bytes(_batchCommand); Array.Copy(buffer, 0, _bufferOut, 0, buffer.Length); Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length); if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE)) { return null; } //receiveLen < MCProtocol.MC_QHEADER_RESPONSE_SIZE means no data in bufferIn int receiveLen = ReceiveData(_bufferIn); int dataLength = receiveLen - MCProtocol.MC_QHEADER_RESPONSE_SIZE; if (dataLength < 0) { return null; } MCProtocol.MC_RESPONSE_HEADER responseHeader = MCProtocol.ToStruct(_bufferIn); if (responseHeader.ProtocolId != 0x00d0 && responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS) { return null; } short[] datas = new short[size]; byte[] dataBuff = new byte[dataLength]; Array.Copy(_bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE, dataBuff, 0, dataBuff.Length); for (int i = 0, dataBuffIndex = 0; i < datas.Length & dataBuffIndex < dataBuff.Length; i++, dataBuffIndex += 2) { datas[i] = (short)BitConverter.ToUInt16(dataBuff, 0 + i * 2); } return datas; } private short[] DoReadAo(int offset, int size) { _batchCommand.DeviceCode = (byte)MelsecElement.ChooseMelsecElement(_aiStoragename).m_nBinCode; _batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_READ; _batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS; _batchCommand.HeadAddr = (ushort)(offset & 0xFFFF); _batchCommand.Reserved = (byte)(offset >> 16); _batchCommand.DevicePoints = (ushort)size; _header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE); byte[] buffer = MCProtocol.Struct2Bytes(_header); byte[] command = MCProtocol.Struct2Bytes(_batchCommand); Array.Copy(buffer, 0, _bufferOut, 0, buffer.Length); Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length); if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE)) { return null; } //receiveLen < MCProtocol.MC_QHEADER_RESPONSE_SIZE means no data in bufferIn int receiveLen = ReceiveData(_bufferIn); int dataLength = receiveLen - MCProtocol.MC_QHEADER_RESPONSE_SIZE; if (dataLength < 0) { return null; } MCProtocol.MC_RESPONSE_HEADER responseHeader = MCProtocol.ToStruct(_bufferIn); if (responseHeader.ProtocolId != 0x00d0 && responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS) { return null; } short[] datas = new short[size]; byte[] dataBuff = new byte[dataLength]; Array.Copy(_bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE, dataBuff, 0, dataBuff.Length); for (int i = 0, dataBuffIndex = 0; i < datas.Length & dataBuffIndex < dataBuff.Length; i++, dataBuffIndex += 2) { datas[i] = (short)BitConverter.ToUInt16(dataBuff, 0 + i * 2); } return datas; } private void DoWriteAo(int offset, short[] data, int total = 0, int count = 100) { ushort[] uData = new ushort[data.Length]; uData = data.Select(x => (ushort)x).ToArray(); _batchCommand.DeviceCode = (byte)MelsecElement.ChooseMelsecElement(_aoStoragename).m_nBinCode; _batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_WRITE; _batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS; _batchCommand.HeadAddr = (ushort)(offset & 0xFFFF); _batchCommand.Reserved = (byte)(offset >> 16); _batchCommand.DevicePoints = (ushort)data.Length; _header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE + MCProtocol.ShortSize * data.Length); byte[] header = MCProtocol.Struct2Bytes(_header); byte[] command = MCProtocol.Struct2Bytes(_batchCommand); byte[] byteData = MCProtocol.Ushort2Byte(uData); Array.Copy(header, 0, _bufferOut, 0, header.Length); Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length); Array.Copy(byteData, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE, byteData.Length); if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.ShortSize * data.Length)) { return; } if (ReceiveData(_bufferIn) <= 0) { return; } MCProtocol.MC_RESPONSE_HEADER responseHeader = MCProtocol.ToStruct(_bufferIn); if (responseHeader.ProtocolId != 0x00d0 && responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS) { LOG.Write(" failed with code," + responseHeader.CompleteCode); return; } } private bool[] DoReadDi(int offset, int size) { _batchCommand.DeviceCode = (byte)MelsecElement.ChooseMelsecElement(_diStoragename).m_nBinCode; _batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_READ; _batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS; _batchCommand.HeadAddr = (ushort)(offset & 0xFFFF); _batchCommand.Reserved = (byte)(offset >> 16); _batchCommand.DevicePoints = (ushort)(size % 16 > 0 ? size / 16 + 1 : size / 16); _header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE); byte[] buffer = MCProtocol.Struct2Bytes(_header); byte[] command = MCProtocol.Struct2Bytes(_batchCommand); Array.Copy(buffer, 0, _bufferOut, 0, buffer.Length); Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length); //50 00 00 ff ff 03 00 0c 00 10 00 01 04 00 00 00 00 00 a0 02 00 00 00 00 00 00 00 00 00 00 00 00 00 if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE)) { return null; } //receiveLen < MCProtocol.MC_QHEADER_RESPONSE_SIZE means no data in bufferIn int receiveLen = ReceiveData(_bufferIn); int dataLength = receiveLen - MCProtocol.MC_QHEADER_RESPONSE_SIZE; if (dataLength < 0) { return null; } MCProtocol.MC_RESPONSE_HEADER responseHeader = MCProtocol.ToStruct(_bufferIn); if (responseHeader.ProtocolId != 0x00d0 && responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS) { return null; } bool[] datas = new bool[dataLength * 8]; byte[] dataBuff = new byte[dataLength]; Array.Copy(_bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE, dataBuff, 0, dataBuff.Length); var bitArray = new BitArray(dataBuff); for (int i = 0; i < datas.Length; i++) { datas[i] = bitArray.Get(i); } return datas.Select(x => x).Take(size).ToArray(); } private bool[] DoReadDo(int offset, int size) { _batchCommand.DeviceCode = (byte)MelsecElement.ChooseMelsecElement(_diStoragename).m_nBinCode; _batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_READ; _batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS; _batchCommand.HeadAddr = (ushort)(offset & 0xFFFF); _batchCommand.Reserved = (byte)(offset >> 16); _batchCommand.DevicePoints = (ushort)(size % 16 > 0 ? size / 16 + 1 : size / 16); _header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE); byte[] buffer = MCProtocol.Struct2Bytes(_header); byte[] command = MCProtocol.Struct2Bytes(_batchCommand); Array.Copy(buffer, 0, _bufferOut, 0, buffer.Length); Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length); //50 00 00 ff ff 03 00 0c 00 10 00 01 04 00 00 00 00 00 a0 02 00 00 00 00 00 00 00 00 00 00 00 00 00 if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE)) { return null; } //receiveLen < MCProtocol.MC_QHEADER_RESPONSE_SIZE means no data in bufferIn int receiveLen = ReceiveData(_bufferIn); int dataLength = receiveLen - MCProtocol.MC_QHEADER_RESPONSE_SIZE; if (dataLength < 0) { return null; } MCProtocol.MC_RESPONSE_HEADER responseHeader = MCProtocol.ToStruct(_bufferIn); if (responseHeader.ProtocolId != 0x00d0 && responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS) { return null; } bool[] datas = new bool[dataLength * 8]; byte[] dataBuff = new byte[dataLength]; Array.Copy(_bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE, dataBuff, 0, dataBuff.Length); var bitArray = new BitArray(dataBuff); for (int i = 0; i < datas.Length; i++) { datas[i] = bitArray.Get(i); } return datas.Select(x => x).Take(size).ToArray(); } private void DoWriteDo(int offset, bool[] data) { _batchCommand.DeviceCode = (byte)MelsecElement.ChooseMelsecElement(_doStoragename).m_nBinCode; _batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_WRITE; _batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS; _batchCommand.HeadAddr = (ushort)(offset & 0xFFFF); _batchCommand.Reserved = (byte)(offset >> 16); _batchCommand.DevicePoints = (ushort)(data.Length % 16 > 0 ? data.Length / 16 + 1 : data.Length / 16); _header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE + _batchCommand.DevicePoints * 2); //one word = two bytes , so _batchCommand.DevicePoints * 2 byte[] byteData = new byte[_batchCommand.DevicePoints * 2]; for (int i = 0, byteDataIndex = 0; i < data.Length & byteDataIndex < byteData.Length; i += 8, byteDataIndex++) { byteData[byteDataIndex] += (byte)(data[i] ? 1 : 0); byteData[byteDataIndex] += (byte)(i + 1 < data.Length && data[i + 1] ? 1 << 1 : 0); byteData[byteDataIndex] += (byte)(i + 2 < data.Length && data[i + 2] ? 1 << 2 : 0); byteData[byteDataIndex] += (byte)(i + 3 < data.Length && data[i + 3] ? 1 << 3 : 0); byteData[byteDataIndex] += (byte)(i + 4 < data.Length && data[i + 4] ? 1 << 4 : 0); byteData[byteDataIndex] += (byte)(i + 5 < data.Length && data[i + 5] ? 1 << 5 : 0); byteData[byteDataIndex] += (byte)(i + 6 < data.Length && data[i + 6] ? 1 << 6 : 0); byteData[byteDataIndex] += (byte)(i + 7 < data.Length && data[i + 7] ? 1 << 7 : 0); } byte[] header = MCProtocol.Struct2Bytes(_header); byte[] command = MCProtocol.Struct2Bytes(_batchCommand); Array.Copy(header, 0, _bufferOut, 0, header.Length); Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length); Array.Copy(byteData, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE, byteData.Length); if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE + byteData.Length)) { return; } if (ReceiveData(_bufferIn) <= 0) { return; } MCProtocol.MC_RESPONSE_HEADER responseHeader = MCProtocol.ToStruct(_bufferIn); if (responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS) { LOG.Write("Write PLC failed with code," + responseHeader.CompleteCode); return; } } } class MCSocket { private int m_nPort; private string m_strAddress; private Socket m_socket; private int m_nTimeOut; public MCSocket() { m_nTimeOut = 30000; } ~MCSocket() { } public bool Connected { get { return (m_socket != null && m_socket.Connected); } } public bool Open(string strAddress, int nPort, string strLocalAddress) { if (Connected) return true; Close(); m_strAddress = strAddress; m_nPort = nPort; m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { // Bind to specific local endpoint IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 0); m_socket.Bind(localEndPoint); IPAddress ipAddress = IPAddress.Parse(m_strAddress); IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, m_nPort); //m_socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); m_socket.SendTimeout = m_nTimeOut; m_socket.ReceiveTimeout = m_nTimeOut; m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); m_socket.Connect(ipEndPoint); } catch (Exception ex) { LOG.Write(ex); return false; } return true; } public bool Close() { if (m_socket == null) return true; try { m_socket.Shutdown(SocketShutdown.Both); m_socket.Close(); m_socket = null; } catch (Exception ex) { LOG.Write(ex); return false; } return true; } public int Read(byte[] buffer) { int ret = -1; if (!Connected) return ret; return m_socket.Receive(buffer); //try //{ // ret = m_socket.Receive(buffer); //} //catch (Exception ex) //{ // LOG.Write(ex); //} //return ret; } public bool Read(byte[] buffer, int length) { if (!Connected) return false; try { m_socket.Receive(buffer, SocketFlags.None); } catch (Exception ex) { LOG.Write(ex); return false; } return true; } public bool Write(byte[] buffer) { if (!Connected) return false; try { m_socket.Send(buffer, SocketFlags.None); } catch (Exception ex) { LOG.Write(ex); return false; } return true; } public bool Write(byte[] buffer, int length) { if (!Connected) return false; return m_socket.Send(buffer, length, SocketFlags.None) >= 0; //try //{ // m_socket.Send(buffer, length, SocketFlags.None); //} //catch (Exception ex) //{ // LOG.Write(ex); // return false; //} //return true; } } }