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.ModBus; using MECF.Framework.Common.IOCore; using MECF.Framework.Common.PLC; using MECF.Framework.RT.Core.IoProviders; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; namespace FurnaceRT.Equipments.Systems { public class ModbusTCP : IoProvider { private string _address; private Int32 _port; private byte _station; public int _diStartAddress; public int _doStartAddress; public int _aiStartAddress; public int _aoStartAddress; public string _dataformat; public bool _addressstartwithzero; public bool _stringReverse; private ModbusTcpNet _readerClient = null; private WcfPlc _wcfPlc = null; public bool IsCommunicationError { get; set; } = false; private R_TRIG _trigRetryConnect = new R_TRIG(); private Stopwatch _stopwatchTotal = new Stopwatch(); private bool _enableLog = true; private int _failCount = 0; protected override void SetParameter(XmlElement nodeParameter) { _address = nodeParameter.GetAttribute("ip"); _port = Convert.ToInt32(nodeParameter.GetAttribute("port")); _station = (byte)Convert.ToInt32(nodeParameter.GetAttribute("station_id")); //_stringReverse = Convert.ToBoolean(nodeParameter.GetAttribute("stringReverse")); _diStartAddress = int.Parse(nodeParameter.GetAttribute("diStartAddress")); _aiStartAddress = int.Parse(nodeParameter.GetAttribute("aiStartAddress")); _doStartAddress = int.Parse(nodeParameter.GetAttribute("doStartAddress")); _aoStartAddress = int.Parse(nodeParameter.GetAttribute("aoStartAddress")); //_dataformat = nodeParameter.GetAttribute("dataformat"); //DisconnectAlarm = SubscribeAlarm($"{Name}.DisconnectAlarm", "", ResetAlarm); //DisconnectAlarm.Id = 1030; //CommunicationErrorAlarm = SubscribeAlarm($"{Name}.DisconnectAlarm", "", ResetAlarm); //CommunicationErrorAlarm.Id = 1031; _enableLog = SC.GetValue($"System.ModbusCommunicationEnableLogMessage"); OP.Subscribe($"Sysytem.{Name}.ModbusPLC", InvokeReset); if (SC.GetValue("System.IsSimulatorMode")) { _wcfPlc = new WcfPlc("System", "Heater", "WcfPlc_Heater"); _wcfPlc.Initialize(); } else { _readerClient = new ModbusTcpNet(_address, _port, _station); Open(); } } public int _connecteTimes { get; set; } private R_TRIG _trigConnected = new R_TRIG(); private R_TRIG _trigReadDoAndAo = new R_TRIG(); //public override bool ResetAlarm() //{ // Reset(); // return true; //} public override void Initialize(string module, string name, List lstBuffers, IIoBuffer buffer, XmlElement nodeParameter, string ioMappingPathFile, string ioModule) { //if (SC.GetValue("System.IsSimulatorMode")) // _wcfPlc.Initialize(); base.Initialize(module, name, lstBuffers, buffer, nodeParameter, ioMappingPathFile, ioModule); } protected override bool OnTimer() { try { _stopwatchTotal.Start(); foreach (var bufferSection in _blockSections) { if (bufferSection.Type == IoType.DI) { bool[] diBuffer = ReadDi(bufferSection.Offset, bufferSection.Size); if (diBuffer != null) { _buffer.SetDiBuffer(_source, bufferSection.Offset, diBuffer); //TraceArray(diBuffer); } } else if (bufferSection.Type == IoType.DO) { if (_trigConnected.Q && !_trigReadDoAndAo.M) { bool[] doBuffer = ReadDo(bufferSection.Offset, bufferSection.Size); if (doBuffer != null) { _buffer.SetDoBuffer(_source, bufferSection.Offset, doBuffer); } } } else if (bufferSection.Type == IoType.AI) { float[] aiBuffer = ReadAiFloat(bufferSection.Offset, bufferSection.Size); if (aiBuffer != null) { _buffer.SetAiBufferFloat(_source, bufferSection.Offset, aiBuffer); } } else if (bufferSection.Type == IoType.AO) { if (_trigConnected.Q && !_trigReadDoAndAo.M) { float[] aoBuffer = ReadAo(bufferSection.Offset, bufferSection.Size); if (aoBuffer != null) { _buffer.SetAoBufferFloat(_source, bufferSection.Offset, aoBuffer); } } } } if (!_trigReadDoAndAo.M) _trigReadDoAndAo.CLK = true; //if (SC.GetValue("System.IsSimulatorMode")) { Dictionary dos = _buffer.GetDoBuffer(_source); if (dos != null) { foreach (var doo in dos) { WriteDo(doo.Key, doo.Value); } } Dictionary aos = _buffer.GetAoBufferFloat(_source); if (aos != null) { foreach (var ao in aos) { WriteAoFloat(ao.Key, ao.Value); } } } var comunicationSpanTotal = (int)_stopwatchTotal.ElapsedMilliseconds; //LOG.Write($"Modbus {comunicationSpanTotal}"); _stopwatchTotal.Restart(); } catch (Exception ex) { LOG.Write(ex); Close(); } return true; } public override void Reset() { _trigError.RST = true; _trigNotConnected.RST = true; if (!_trigConnected.M) { if (!SC.GetValue("System.IsSimulatorMode")) { Close(); Open(); } } } private void TrigDisconnectAlarm() { _trigNotConnected.CLK = true; if (_trigNotConnected.T) { EV.PostInfoLog(Module, $"{Module} {_address}:{_port} connected"); } if (_trigNotConnected.R) { EV.PostAlarmLog(Module, $"{Module} {_address}:{_port} not connected"); } } protected override bool[] ReadDi(int offset, int size) { if (SC.GetValue("System.IsSimulatorMode")) { int address = offset + _aiStartAddress; var ret = _wcfPlc.ReadBool(address.ToString(), out bool[] data, size, out _); return data; } else { if (_trigNotConnected.M) return null; var dataDi = DATA.Poll($"System.Heater.DIItemList"); bool[] data = new bool[size]; if (dataDi != null) { List item = (List)dataDi; int address = _diStartAddress; int iOldAddress = _diStartAddress; ushort iCount = 0; int iIndex = 0; for (int i = 0; i < item.Count; i++) { int.TryParse(item[i].Address, out int iNewAddress); if (iNewAddress == iOldAddress) { iCount++; continue; } else { if (iNewAddress == iOldAddress + 1) { iCount++; iOldAddress = iNewAddress; } else { var ret = _readerClient.ReadInt16(address.ToString(), iCount); if (ret.IsSuccess) { for (int j = 0; j < ret.Content.Length; j++) { data[iIndex + j] = ret.Content[j] > 0 ? true : false; } _failCount = 0; } else { _failCount++; } iIndex = iNewAddress - _diStartAddress; address = iNewAddress; iOldAddress = iNewAddress; iCount = 1; } } if (i == item.Count - 1) { var ret = _readerClient.ReadInt16(address.ToString(), iCount); if (ret.IsSuccess) { for (int j = 0; j < ret.Content.Length; j++) { data[iIndex + j] = ret.Content[j] > 0 ? true : false; } _failCount = 0; } else { _failCount++; } } } } if (_failCount >= 5) TrigDisconnectAlarm(); return data; } } protected override float[] ReadAiFloat(int offset, int size) { if (SC.GetValue("System.IsSimulatorMode")) { int address = offset + _aiStartAddress; var ret = _wcfPlc.ReadFloat(address.ToString(), out float[] data, size, out _); return data; } else { if (_trigNotConnected.M) return null; var dataAi = DATA.Poll($"System.Heater.AIItemList"); float[] data = new float[size]; if (dataAi != null) { List item = (List)dataAi; int address = _aiStartAddress; int iOldAddress = _aiStartAddress; ushort iCount = 0; int iIndex = 0; for (int i = 0; i < item.Count; i++) { int.TryParse(item[i].Address, out int iNewAddress); if (iNewAddress == iOldAddress) { iCount++; continue; } else { if (iNewAddress == iOldAddress + 2) { iCount++; iOldAddress = iNewAddress; } else { var ret = _readerClient.ReadFloatAsync(address.ToString(), iCount); if (ret.Result.IsSuccess) { for (int j = 0; j < ret.Result.Content.Length; j++) { data[iIndex + j * 2] = ret.Result.Content[j]; } } iIndex = iNewAddress - _aiStartAddress; address = iNewAddress; iOldAddress = iNewAddress; iCount = 1; } } if (i == item.Count - 1) { var ret = _readerClient.ReadFloatAsync(address.ToString(), iCount); if (ret.Result.IsSuccess) { for (int j = 0; j < ret.Result.Content.Length; j++) { data[iIndex + j * 2] = ret.Result.Content[j]; } } } } } return data; } } protected bool[] ReadDo(int offset, int size) { if (SC.GetValue("System.IsSimulatorMode")) { return null; } else { var dataDo = DATA.Poll($"System.Heater.DOItemList"); bool[] data = new bool[size]; if (dataDo != null) { List item = (List)dataDo; int address = _doStartAddress; int iOldAddress = _doStartAddress; ushort iCount = 0; int iIndex = 0; for (int i = 0; i < item.Count; i++) { int.TryParse(item[i].Address, out int iNewAddress); if (iNewAddress == iOldAddress) { iCount++; continue; } else { if (iNewAddress == iOldAddress + 1) { iCount++; iOldAddress = iNewAddress; } else { var ret = _readerClient.ReadInt16(address.ToString(), iCount); if (ret.IsSuccess) { for (int j = 0; j < ret.Content.Length; j++) { data[iIndex + j] = ret.Content[j] > 0 ? true : false; } } iIndex = iNewAddress - _doStartAddress; address = iNewAddress; iOldAddress = iNewAddress; iCount = 1; } } if (i == item.Count - 1) { var ret = _readerClient.ReadInt16(address.ToString(), iCount); if (ret.IsSuccess) { for (int j = 0; j < ret.Content.Length; j++) { data[iIndex + j] = ret.Content[j] > 0 ? true : false; } } } } } return data; } } protected override short[] ReadAi(int offset, int size) { if (SC.GetValue("System.IsSimulatorMode")) { int address = offset + _aiStartAddress; var ret = _wcfPlc.ReadInt16(address.ToString(), out short[] data, size, out _); return data; } else { int address = offset + _aiStartAddress; var ret = _readerClient.ReadInt16(address.ToString(), (ushort)size); if (!ret.IsSuccess) return null; return ret.Content; } } protected float[] ReadAo(int offset, int size) { if (SC.GetValue("System.IsSimulatorMode")) { return null; } else { var dataAo = DATA.Poll($"System.Heater.AOItemList"); float[] data = new float[size]; if (dataAo != null) { List item = (List)dataAo; int address = _aoStartAddress; int iOldAddress = _aoStartAddress; ushort iCount = 0; int iIndex = 0; for (int i = 0; i < item.Count; i++) { int.TryParse(item[i].Address, out int iNewAddress); if (iNewAddress == iOldAddress) { iCount++; continue; } else { if (iNewAddress == iOldAddress + 2) { iCount++; iOldAddress = iNewAddress; } else { var ret = _readerClient.ReadFloat(address.ToString(), iCount); if (ret.IsSuccess) { for (int j = 0; j < ret.Content.Length; j++) { data[iIndex + j * 2] = ret.Content[j]; } } iIndex = iNewAddress - _aoStartAddress; address = iNewAddress; iOldAddress = iNewAddress; iCount = 1; } } if (i == item.Count - 1) { var ret = _readerClient.ReadFloat(address.ToString(), iCount); if (ret.IsSuccess) { for (int j = 0; j < ret.Content.Length; j++) { data[iIndex + j * 2] = ret.Content[j]; } } } } } return data; } } public override bool SetValueFloat(AOAccessor aoItem, float value) { if (SC.GetValue("System.IsSimulatorMode")) return true; if (!_trigConnected.M) return false; if (_trigNotConnected.M) return false; try { int address = aoItem.Index + _aoStartAddress; var ret = _readerClient.Write(address.ToString(), new float[] { value }); return ret.IsSuccess; } catch (Exception) { _trigConnected.CLK = false; return false; } } public override bool SetValue(DOAccessor doItem, bool value) { if (SC.GetValue("System.IsSimulatorMode")) return true; if (!_trigConnected.M) return false; if (_trigNotConnected.M) return false; try { int address = doItem.Index + _doStartAddress; var ret2 = _readerClient.Write(address.ToString(), (short)(value ? 1 : 0)); return ret2.IsSuccess; } catch (Exception) { _trigConnected.CLK = false; return false; } } protected override void Close() { try { _readerClient.ConnectClose(); _readerClient.Dispose(); _trigConnected.RST = true; } catch (Exception ex) { LOG.Write(ex.Message); } } protected override void Open() { _readerClient.IpAddress = _address; _readerClient.Port = _port; _readerClient?.ConnectClose(); try { var ret = _readerClient.ConnectServer(); if (ret.IsSuccess) _trigConnected.CLK = true; else { //DisconnectAlarm.Description = ret.Message; //DisconnectAlarm.Set(); LOG.Write(ret.Message); } } catch (Exception ex) { IsCommunicationError = true; LOG.Write(ex.Message); //CommunicationErrorAlarm.Description = ex.Message; //CommunicationErrorAlarm.Set(); } } public byte[] ReadResultRender(OperateResult result, string address) { byte[] buffer = new byte[32]; if (result.IsSuccess) { _connecteTimes = 0; IsCommunicationError = false; var dat2 = (Convert.ToUInt32(result.Content.ToString()) & 0xFFFF); var dat1 = (Convert.ToUInt32(result.Content.ToString()) >> 16 & 0xFFFF); uint[] data = new uint[] { dat1, dat2 }; for (int j = 0; j < 2; j++) { for (int i = 0; i < 16; i++) { buffer[j * 16 + i] = Convert.ToByte((data[j] >> i) & 0x01); } } string str = string.Join("", Array.ConvertAll(buffer, x => x.ToString())); if (_enableLog) LOG.Info($"Read Success,Data:{ str} ({ result.Content.ToString()}:{dat1}、{dat2})"); return buffer; } else { IsCommunicationError = true; EV.PostAlarmLog("System.PLC", $"[{address}] Read Failed {Environment.NewLine}Reason:{result.ToMessageShowString()}"); } return buffer; } public void WriteResultRender(OperateResult result, string address, int data, string str) { if (result.IsSuccess) { _connecteTimes = 0; IsCommunicationError = false; if (_enableLog) LOG.Info("Write Success,Data" + str + "(" + data.ToString() + ")"); } else { IsCommunicationError = true; EV.PostAlarmLog("System.PLC", $"[{address}] Write Failed {Environment.NewLine}Reason:{result.ToMessageShowString()}"); } } public bool InvokeReset(string arg1, object[] arg2) { _connecteTimes = 0; IsCommunicationError = false; _trigRetryConnect.RST = true; return true; } protected override void WriteDo(int offset, bool[] buffer) { if (_readerClient != null) { return; int address = offset + _doStartAddress; List temp = new List(); for(int i=0;i 0) { temp = new float[data.Length - i * size]; Array.Copy(data, i * size, temp, 0, data.Length - i * size); var ret = _readerClient.Write((address + i * size).ToString(), temp); if (!ret.IsSuccess) { return; } } } else { int address = offset + _aoStartAddress; _wcfPlc?.WriteFloat(address.ToString(), data, out _); } } } }