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 HslCommunication; using HslCommunication.Profinet.Omron; 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 FinsProtocolPlc : 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 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 OmronFinsUdp _omronFinsUdp = null; private string _aiStoragename = "R"; private string _aoStoragename = "R"; private string _diStoragename = "B"; private string _doStoragename = "B"; 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); State = IoProviderStateEnum.Uninitialized; _thread = new PeriodicJob(30, OnTimer, name); ConnectionManager.Instance.Subscribe(Name, this); OP.Subscribe($"{Name}.Reconnect", (string cmd, object[] args) => { Close(); Open(); return true; }); } protected override bool OnTimer() { if (State == IoProviderStateEnum.Uninitialized) { 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"); 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() { _bufferOut = new byte[2048]; _bufferIn = new byte[2048]; _omronFinsUdp = new OmronFinsUdp(_ip, _port); SetState(IoProviderStateEnum.Opened); } protected override void Close() { SetState(IoProviderStateEnum.Closed); } protected override bool[] ReadDi(int offset, int size) { bool[] ret = new bool[size]; string address = $"{_diStoragename}{offset + _diStartAddress}"; if (_diStoragename == "B") { address = $"{_diStoragename}{(offset + _diStartAddress).ToString("X")}"; } ushort readsize = (ushort)(size / 16); if (size % 16 != 0) readsize += 1; OperateResult result = _omronFinsUdp.ReadUInt16(address, (ushort)readsize); if (!result.IsSuccess) { LOG.Write($"PLC {_omronFinsUdp.IpAddress} read DI failed:{result.Message}."); return null; } for (int i = 0; i < size; i++) { int valueIndex = i / 16; int valueOffset = i % 16; ret[i] = ((result.Content[valueIndex] & (short)Math.Pow(2, valueOffset)) == Math.Pow(2, valueOffset)); } return ret; } protected bool[] ReadDo(int offset, int size) { bool[] ret = new bool[size]; string address = $"{_doStoragename}{offset + _doStartAddress}"; if (_doStoragename == "B") { address = $"{_doStoragename}{(offset + _doStartAddress).ToString("X")}"; } ushort readsize = (ushort)(size / 16); if (size % 16 != 0) readsize += 1; OperateResult result = _omronFinsUdp.ReadUInt16(address, (ushort)readsize); if (!result.IsSuccess) { LOG.Write($"PLC {_omronFinsUdp.IpAddress} read DO failed:{result.Message}."); return null; } for (int i = 0; i < size; i++) { int valueIndex = i / 16; int valueOffset = i % 16; ret[i] = ((result.Content[valueIndex] & (short)Math.Pow(2, valueOffset)) == Math.Pow(2, valueOffset)); } return ret; } protected override short[] ReadAi(int offset, int size) { OperateResult result = _omronFinsUdp.ReadInt16($"{_aiStoragename}{offset + _aiStartAddress}", (ushort)size); if (result.IsSuccess) return result.Content; LOG.Write($"PLC {_omronFinsUdp.IpAddress} read AI failed,error code:{result.ErrorCode},{result.Message}."); return null; } protected short[] ReadAo(int offset, int size) { OperateResult result = _omronFinsUdp.ReadInt16($"{_aoStoragename}{offset + _aoStartAddress}", (ushort)size); if (result.IsSuccess) return result.Content; LOG.Write($"PLC {_omronFinsUdp.IpAddress} read AO failed,error code:{result.ErrorCode},{result.Message}."); return null; } protected override void WriteDo(int offset, bool[] buffer) { string address; OperateResult result = new OperateResult(); int shortsize = (buffer.Length - 1) / 16 + 1; ushort[] value = new ushort[shortsize]; for (int i = 0; i < shortsize; i++) { value[i] = 0; for (int j = i * 16; j < (i + 1) * 16; j++) { if (buffer.Length > j && buffer[j]) { value[i] += (ushort)Math.Pow(2, j - (16 * i)); } } } address = $"{_doStoragename}{offset + _doStartAddress}"; if (_doStoragename == "B") { address = $"{_doStoragename}{(offset + _doStartAddress).ToString("X")}"; } result = _omronFinsUdp.Write(address, value); if (result.IsSuccess) return; LOG.Write($"PLC {_omronFinsUdp.IpAddress} write DO failed:{result.Message}."); } protected override void WriteAo(int offset, short[] buffer) { OperateResult result; int startAddress = offset + _aoStartAddress; int blockCount = (buffer.Length - 1) / 960 + 1; for (int i = 0; i < blockCount; i++) { if (i == blockCount - 1) { result = _omronFinsUdp.Write($"{_aoStoragename}{startAddress + i * 960}", buffer.Skip(i * 960).Take(buffer.Length - 960 * i).ToArray()); } else { result = _omronFinsUdp.Write($"{_aoStoragename}{startAddress + i * 960}", buffer.Skip(i * 960).Take(960).ToArray()); } if (!result.IsSuccess) LOG.Write($"PLC {_omronFinsUdp.IpAddress} write AO failed:{result.Message}."); } } } }