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.Common.PLC; 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 FinsPlcAdapter : 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 int _heartBeat; public int HeartBeat { get { { if (_heartBeat > 65535) { _heartBeat = 0; } return _heartBeat++; } } } //private string _localIp = "127.0.0.1"; //private int _socketId = 101; //private int _stationId = 102; private IPlc _plc = null; //private bool _isOpened = false; private string _ip = "192.168.10.10"; private int _port = 9600; private int _aoBlockStartPosition = 1000; private int _aiBlockStartPosition = 2000; private int _doBlockStartPosition = 0; private int _diBlockStartPosition = 20; private string _diBlockType = "W"; private string _doBlockType = "W"; private string _aiBlockType = "D"; private string _aoBlockType = "D"; R_TRIG _failedTrigger = new R_TRIG(); 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 _trigConnected = new R_TRIG(); private Dictionary _logTrigDic = new Dictionary(); private int plcCollectionInterval; private string _ioModule; public override void Initialize(string module, string name, List lstBuffers, IIoBuffer buffer, XmlElement nodeParameter, string ioMappingPathFile, string ioModule) { Module = module; Name = name; _source = module + "." + name; _buffer = buffer; _ioModule = ioModule; _nodeParameter = nodeParameter; _blockSections = lstBuffers; buffer.SetBufferBlock(_source, lstBuffers); buffer.SetIoMapByModule(_source, 0, ioMappingPathFile, ioModule); SetParameter(nodeParameter); State = IoProviderStateEnum.Uninitialized; plcCollectionInterval = SC.ContainsItem("System.PlcCollectionInterval") ? SC.GetValue("System.PlcCollectionInterval") : 50; _thread = new PeriodicJob(plcCollectionInterval, OnTimer, name); ConnectionManager.Instance.Subscribe(Name, this); DATA.Subscribe($"{Module}.{Name}.IsConnected", () => _plc == null ? false : _plc.CheckIsConnected()); DATA.Subscribe($"{Module}.{Name}.Address", () => $"{_ip}:{_port}"); DATA.Subscribe($"{Module}.{Name}.ComunicationSpanTotal", () => comunicationSpanTotal); OP.Subscribe($"{Module}.{Name}.Reconnect", (string cmd, object[] args) => { Close(); Open(); return true; }); //if (SC.GetValue("System.IsSimulatorMode")) //{ // Open(); //} } protected override bool OnTimer() { if (_plc == null) { Open(); } if (_plc == null || !_plc.CheckIsConnected()) return true; _trigConnected.CLK = _plc.CheckIsConnected(); 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); } stopwatchDi.Stop(); } else if (bufferSection.Type == IoType.AI) { stopwatchAi.Start(); if (bufferSection.AIOType == typeof(float)) { float[] aiBuffer = ReadAiFloat(bufferSection.Offset, bufferSection.Size); if (aiBuffer != null) { _buffer.SetAiBufferFloat(_source, bufferSection.Offset, aiBuffer); } } else { short[] aiBuffer = ReadAi(bufferSection.Offset, bufferSection.Size); if (aiBuffer != null) { _buffer.SetAiBuffer(_source, bufferSection.Offset, aiBuffer); } } stopwatchAi.Stop(); } else if (bufferSection.Type == IoType.DO) { if (_trigConnected.Q) { bool[] doBuffer = ReadDo(bufferSection.Offset, bufferSection.Size); if (doBuffer != null) { _buffer.SetDoBuffer(_source, bufferSection.Offset, doBuffer); } } //if (SC.GetValue("System.IsSimulatorMode")) { Dictionary dos = _buffer.GetDoBuffer(_source); if (dos != null) { foreach (var doo in dos) { WriteDo(bufferSection.Offset, doo.Value); } } continue; } } else if (bufferSection.Type == IoType.AO) { if (bufferSection.AIOType == typeof(float)) { if (_trigConnected.Q) { float[] aoBuffer = ReadAoFloat(bufferSection.Offset, bufferSection.Size); if (aoBuffer != null) { _buffer.SetAoBufferFloat(_source, bufferSection.Offset, aoBuffer); } } //if (SC.GetValue("System.IsSimulatorMode")) { Dictionary aos = _buffer.GetAoBufferFloat(_source); if (aos != null) { foreach (var ao in aos) { WriteAoFloat(bufferSection.Offset, ao.Value); } } continue; } } else { if (_trigConnected.Q) { short[] aoBuffer = ReadAo(bufferSection.Offset, bufferSection.Size); if (aoBuffer != null) { _buffer.SetAoBuffer(_source, bufferSection.Offset, aoBuffer); } } //if (SC.GetValue("System.IsSimulatorMode")) { Dictionary aos = _buffer.GetAoBuffer(_source); if (aos != null) { foreach (var ao in aos) { WriteAo(bufferSection.Offset, ao.Value); } } continue; } } } } //comunicationSpanDi = (int)stopwatchDi.ElapsedMilliseconds; stopwatchDi.Reset(); //comunicationSpanAi = (int)stopwatchAi.ElapsedMilliseconds; stopwatchAi.Reset(); comunicationSpanTotal = (int)stopwatchTotal.ElapsedMilliseconds; stopwatchTotal.Restart(); } catch (Exception ex) { LOG.Error($"{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"); string strPort = nodeParameter.GetAttribute("port"); string diBlockType = nodeParameter.GetAttribute("diStoragename"); string doBlockType = nodeParameter.GetAttribute("doStoragename"); string aiBlockType = nodeParameter.GetAttribute("aiStoragename"); string aoBlockType = nodeParameter.GetAttribute("aoStoragename"); string diStartPosition = nodeParameter.GetAttribute("diStartAddress"); string doStartPosition = nodeParameter.GetAttribute("doStartAddress"); string aiStartPosition = nodeParameter.GetAttribute("aiStartAddress"); string aoStartPosition = nodeParameter.GetAttribute("aoStartAddress"); _port = int.Parse(strPort); _ip = strIp; _diBlockType = nodeParameter.GetAttribute("diStoragename").Substring(0, 1); _doBlockType = nodeParameter.GetAttribute("doStoragename").Substring(0, 1); _aiBlockType = nodeParameter.GetAttribute("aiStoragename").Substring(0, 1); _aoBlockType = nodeParameter.GetAttribute("aoStoragename").Substring(0, 1); if (!int.TryParse(diStartPosition, out _diBlockStartPosition)) { LOG.Error($"plc config error, start position {diStartPosition} not valid"); } if (!int.TryParse(doStartPosition, out _doBlockStartPosition)) { LOG.Error($"plc config error, start position {doStartPosition} not valid"); } if (!int.TryParse(aiStartPosition, out _aiBlockStartPosition)) { LOG.Error($"plc config error, start position {aiStartPosition} not valid"); } if (!int.TryParse(aoStartPosition, out _aoBlockStartPosition)) { LOG.Error($"plc config error, start position {aoStartPosition} not valid"); } } public override void Reset() { _trigError.RST = true; _trigNotConnected.RST = true; foreach (var trig in _logTrigDic.Values) { if (trig != null) trig.RST = true; } if (!_plc.CheckIsConnected()) { Close(); Open(); } } protected override void Open() { if (SC.GetValue("System.IsSimulatorMode")) { _plc = new WcfPlc(Module, Name, $"WcfPlc_{Name}"); _plc.Initialize(); } else { _plc = new FinsPlc(_ip, _port); } try { OperateResult connect = _plc.Connect() ? OperateResult.CreateSuccessResult() : new OperateResult(); if (connect.IsSuccess) { SetState(IoProviderStateEnum.Opened); EV.PostInfoLog(Module, $"{Name} plc connect success"); } else { EV.PostInfoLog(Module, $"{Name} plc connect fail"); } } catch (Exception ex) { LOG.Error(ex.Message); } } protected override void Close() { _plc.Disconnect(); SetState(IoProviderStateEnum.Closed); } protected override bool[] ReadDi(int offset, int size) { bool[] buff = DoReadDi(offset, (ushort)size); return buff; } protected bool[] ReadDo(int offset, int size) { bool[] buff = DoReadDo(offset, (ushort)size); return buff; } protected override short[] ReadAi(int offset, int size) { short[] buff = DoReadAi(offset, (ushort)size); return buff; } protected override float[] ReadAiFloat(int offset, int size) { float[] buff = DoReadAiFloat(offset, (ushort)size); return buff; } protected float[] ReadAoFloat(int offset, int size) { float[] buff = DoReadAoFloat(offset, (ushort)size); return buff; } protected short[] ReadAo(int offset, int size) { short[] buff = DoReadAo(offset, (ushort)size); return buff; } protected override void WriteDo(int offset, bool[] data) { DoWriteDo(offset, data); } protected override void WriteAo(int offset, short[] data) { DoWriteAo(offset, data); } protected override void WriteAoFloat(int offset, float[] data) { DoWriteAoFloat(offset, data); } public override bool SetValue(AOAccessor aoItem, short value) { if (!SC.GetValue("System.IsSimulatorMode")) return true; if (State != IoProviderStateEnum.Opened) return false; return DoWriteAo(aoItem.Index, new[] { value }); } public override bool SetValueFloat(AOAccessor aoItem, float value) { if (!SC.GetValue("System.IsSimulatorMode")) return true; if (State != IoProviderStateEnum.Opened) return false; return DoWriteAoFloat(aoItem.Index, new[] { value }); } public override bool SetValue(DOAccessor doItem, bool value) { if (!SC.GetValue("System.IsSimulatorMode")) return true; var offset = doItem.Index / 16; var index = doItem.Index % 16; int data = 0; for (int i = 0; i < 16; i++) { if (i == index) data += (value ? (1 << i) : (0 << i)); else data += (doItem.Buffer[offset * 16 + i] ? (1 << i) : (0 << i)); } if (_plc.WriteInt16($"{_doBlockType}{_doBlockStartPosition + offset}", new[] { (short)data }, out string reason)) { return true; } var key = "DoWriteAo"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); return false; } #region PLC read write private short[] DoReadAi(int offset, ushort size) { if (_plc.ReadInt16($"{_aiBlockType}{_aiBlockStartPosition + offset}", out short[] result, size, out string reason)) { return result; } var key = "DoReadAi"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); return null; } private float[] DoReadAiFloat(int offset, ushort size) { if (_plc.ReadFloat($"{_aiBlockType}{_aiBlockStartPosition + offset}", out float[] result, size, out string reason)) { return result; } var key = "DoReadAiFloat"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); return null; } private short[] DoReadAo(int offset, ushort size) { if (_plc.ReadInt16($"{_aoBlockType}{_aoBlockStartPosition + offset}", out short[] result, size, out string reason)) { return result; } var key = "DoReadAo"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); return null; } private float[] DoReadAoFloat(int offset, ushort size) { if (_plc.ReadFloat($"{_aoBlockType}{_aoBlockStartPosition + offset}", out float[] result, size, out string reason)) { return result; } var key = "DoReadAoFloat"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); return null; } private bool DoWriteAoFloat(int offset, float[] data, int total = 0, int count = 100) { var reason = ""; if (SC.GetValue("System.IsSimulatorMode")) { if (_plc.WriteFloat($"{_aoBlockType}{_aoBlockStartPosition + offset}", data, out reason)) { return true; } } int size = 450; float[] temp; int i = 0; for (; i< data.Length/ size; i++) { temp = new float[size]; Array.Copy(data, i*size,temp,0,size); if (!_plc.WriteFloat($"{_aoBlockType}{_aoBlockStartPosition + i * size * 2}", temp, out reason)) { return false; } } if(data.Length - i * size > 0) { temp = new float[data.Length - i * size]; Array.Copy(data, i * size, temp, 0, data.Length - i * size); if (!_plc.WriteFloat($"{_aoBlockType}{_aoBlockStartPosition + i * size * 2}", temp, out reason)) { return false; } } return true; //if (_plc.WriteFloat($"{_aoBlockType}{_aoBlockStartPosition + offset}", data, out reason)) //{ // return true; //} var key = "DoWriteAoFloat"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); return false; } private bool DoWriteAo(int offset, short[] data, int total = 0, int count = 100) { if (_plc.WriteInt16($"{_aoBlockType}{_aoBlockStartPosition + offset}", data, out string reason)) { return true; } var key = "DoWriteAo"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); return false; } private bool[] DoReadDi(int offset, ushort size) { if (SC.GetValue("System.IsSimulatorMode")) { if (_plc.ReadBool($"{_diBlockType}{_diBlockStartPosition + (offset >> 4)}.{offset & 0x0f}", out bool[] result, size, out string reason)) { return result; } var key = "DoReadDi"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); } else { var shortSize = size / 16; if (_plc.ReadInt16($"{_diBlockType}{_diBlockStartPosition + offset}", out short[] result, shortSize, out string reason)) { bool[] boolResult = new bool[Math.Min(size, result.Length * 16)]; for (int i = 0; i < shortSize && i < result.Length; i++) { var data = (ushort)result[i]; for (int j = 0; j < 16; j++) { boolResult[i * 16 + j] = Converter.GetBit(data, j); } } return boolResult; } var key = "DoReadDi"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); } return null; } private bool[] DoReadDo(int offset, ushort size) { if (SC.GetValue("System.IsSimulatorMode")) { return null; //if (_plc.ReadBool($"{_doBlockType}{_doBlockStartPosition + (offset >> 4)}.{offset & 0x0f}", out bool[] result, size, out string reason)) //{ // return result; //} //var key = "DoReadDo"; //if (!_logTrigDic.ContainsKey(key)) // _logTrigDic.Add(key, new R_TRIG()); //_logTrigDic[key].CLK = true; //if (_logTrigDic[key].Q) // LOG.Write(reason); } else { var shortSize = size / 16; if (_plc.ReadInt16($"{_doBlockType}{_doBlockStartPosition + offset}", out short[] result, shortSize, out string reason)) { bool[] boolResult = new bool[Math.Min(size, result.Length * 16)]; for (int i = 0; i < shortSize && i < result.Length; i++) { var data = (ushort)result[i]; for (int j = 0; j < 16; j++) { boolResult[i * 16 + j] = Converter.GetBit(data, j); } } return boolResult; } var key = "DoReadDo"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); } return null; } private bool DoWriteDo(int offset, bool[] data) { if (SC.GetValue("System.IsSimulatorMode")) { if (_plc.WriteBool($"{_doBlockType}{_doBlockStartPosition + (offset >> 4)}.{offset & 0x0f}", data, out string reason)) { return true; } var key = "DoWriteDo"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); } else { short[] shortValue = new short[data.Length / 16]; for (int i = 0; i < shortValue.Length; i++) { short value = shortValue[i]; for (int j = 0; j < 16; j++) { value = (short)Converter.SetBit((ushort)value, j, data[i * 16 + j]); } shortValue[i] = value; } if (_plc.WriteInt16($"{_doBlockType}{_doBlockStartPosition + offset}", shortValue, out string reason)) { return true; } var key = "DoWriteDo"; if (!_logTrigDic.ContainsKey(key)) _logTrigDic.Add(key, new R_TRIG()); _logTrigDic[key].CLK = true; if (_logTrigDic[key].Q) LOG.Write(reason); } return false; } #endregion } }