using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using SystemX.Net.Platform.Common.Event; using SystemX.Net.Platform.Common.Util; using static SystemX.PLC.Interface.PLCCommDefinition; namespace SystemX.PLC.Interface.McProtocol { public class PLCCommMcPMgr : PLCCommManager { private int TimeOut; public Dictionary PLCManagers { get; set; } = new Dictionary(); public PLCCommMcPMgr(string strPLCConnInfoXmlPath) : base(strPLCConnInfoXmlPath) { AddrMgr = new PLCAddressManager(strPLCConnInfoXmlPath); EventChangeUpdate = new FunctionEventHandler(); TimeOut = 0; foreach (PLCConnectionInfo coninfo in AddrMgr.ConnInfoDictionary.Values) { if (TimeOut < int.Parse(coninfo.Timeout)) TimeOut = int.Parse(coninfo.Timeout); PLCManagers.Add((ePLCRWType)Enum.Parse(typeof(ePLCRWType), coninfo.RWType), new PLCModMxCMgr(coninfo)); } } public override bool OpenPLCConnection() { Task openconn = new Task(() => TryOpenPLCConnection()); openconn.Start(); bool bResult = openconn.Result; if (bResult) { //Task plcoperation = openconn.ContinueWith(x => StartPLCOperation()); Task plcoperation = new Task(() => StartPLCOperation()); plcoperation.Start(); bResult = plcoperation.Result; } return bResult; /* if (plcoperation.Wait(TimeOut)) return true; else return false; */ } public bool TryOpenPLCConnection() { try { foreach (PLCModMxCMgr conmgr in PLCManagers.Values) { if (!conmgr.OpenDevice()) return false; Stopwatch stTimeOut = new Stopwatch(); stTimeOut.Start(); while (true) { if (conmgr.IsOpened == true) break; if (stTimeOut.ElapsedMilliseconds >= TimeOut) { LogMessage.MessageOutput.ConsoleWrite("PLC Connection Waiting TimeOut.", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); return false; } Thread.Sleep(50); } conmgr.EventPLC += ReceivePLCEvent; SetAddress(conmgr, AddrMgr.OperationDictionary); SetAddress(conmgr, AddrMgr.DataDictionary); } LogMessage.MessageOutput.ConsoleWrite("PLC Connection Waiting for Success.", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE); return true; } catch (Exception ex) { LogMessage.MessageOutput.ConsoleWrite($"PLC Connection Open Error.\n - Error Message: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); return false; } } public override bool StartPLCOperation() { try { Thread.Sleep(300); PLCManagers[ePLCRWType.Read].SingleScanStartAsync(); // Do not use await UpdateAll(); OperationStarted = true; LogMessage.MessageOutput.ConsoleWrite("PLC Operation Started.", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE); return true; } catch (Exception ex) { LogMessage.MessageOutput.ConsoleWrite($"PLC Connection Open Error.\n - Error Message: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); return false; } } public override void NowScanDataArea() { } public override bool ClosePLCConnection() { try { foreach (PLCModMxCMgr conmgr in PLCManagers.Values) conmgr.CloseDevice(); OperationStarted = false; return true; } catch (Exception ex) { LogMessage.MessageOutput.ConsoleWrite($"PLC Connection Close Error.\n - Error Message: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); return false; } } public override void ReceivePLCEvent(string address, int value) { PLCAddressTemplate tmpltSearch = SearchMySubscription(address); if (tmpltSearch == null) return; UpdateDevice(tmpltSearch, address, value); EventChangeUpdate.DoReceive(this, address); } public PLCAddressTemplate SearchMySubscription(string strAddress) { PLCAddressTemplate tmpltOp = AddrMgr.FindPLCAddressElementByAssociatedKeyAddress(strAddress, AddrMgr.OperationDictionary); PLCAddressTemplate tmpltData = AddrMgr.FindPLCAddressElementByAssociatedKeyAddress(strAddress, AddrMgr.DataDictionary); if (tmpltOp != null) return tmpltOp; else return tmpltData; } void SetAddress(PLCModMxCMgr module, Dictionary addressInfo) { foreach (PLCAddressTemplate addrinfo in addressInfo.Values) { int nLength = Convert.ToInt32(addrinfo.Length); int nStartAddr = Convert.ToInt32(addrinfo.Address); for (int i = 0; i < nLength; i++) { int nAddr = nStartAddr + i; module.AddDevices(addrinfo.Area + nAddr.ToString()); } } } public PLCAddressTemplate UpdateDevice(PLCAddressTemplate tmplt, string strDevice, int nValue) { if (tmplt == null) { LogMessage.MessageOutput.ConsoleWrite($"Cannot Find a Corresponding Data. Device: {strDevice}"); return null; } tmplt.UpdateValue(strDevice, nValue); return tmplt; } public PLCAddressTemplate UpdateDevice(string strDevice) { PLCAddressTemplate tmplt = AddrMgr.FindPLCAddressElement(strDevice); if (tmplt == null) { LogMessage.MessageOutput.ConsoleWrite($"Cannot Find a Corresponding Data. Device: {strDevice}"); return null; } UpdateValue(tmplt); return tmplt; } void UpdateValue(PLCAddressTemplate tmplt) { List vValues = GetReadValues(tmplt); eDataType eType = (eDataType)Enum.Parse(typeof(eDataType), tmplt.DataType); string strData = string.Empty; tmplt.SetAssociatedValues(vValues); } public override string ReadDevice(string strDevice, bool bRefineWrongChar = true) { PLCAddressTemplate tmplt = UpdateDevice(strDevice); return (tmplt != null) ? tmplt.Value : string.Empty; } public override string ReadDevice(PLCAddressTemplate tmplt) { try { tmplt = UpdateDevice(tmplt.AddressKey); return (tmplt != null) ? tmplt.Value : string.Empty; } catch (Exception ex) { LogMessage.MessageOutput.ConsoleWrite($"PLC Manager is failed to Read Device. The Address: {tmplt.AddressKey} has not been read by unidentified errors. ", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); LogMessage.MessageOutput.ConsoleWrite($" - Error Message: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); return string.Empty; } } public override void UpdateAll(bool bRefineWrongChar = false) { UpdateArea(AddrMgr.OperationDictionary.Keys.ToList()); UpdateArea(AddrMgr.DataDictionary.Keys.ToList()); } public virtual void SelectUpdate(PLCAddressTemplate tmplt, bool bRefineWrongChar) { } void UpdateArea(List strKeys) { foreach (string strKey in strKeys) UpdateDevice(strKey); } public override bool WriteDevice(PLCAddressTemplate tmplt, string strValue, bool bVerification = false) { try { tmplt.SetStringValue(strValue); WriteDevice(tmplt); if (bVerification) { string strReadValue = ReadDevice(tmplt.PLCAddress); if (strReadValue == strValue) { LogMessage.MessageOutput.ConsoleWrite($"The Address: {tmplt.PLCAddress} has not been written #Intent:{strValue} - #Actual:{tmplt.Value} by unidentified errors. ", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE); return false; } } return true; } catch (Exception ex) { LogMessage.MessageOutput.ConsoleWrite($"PLC Manager is failed to Write Device. The Address: {tmplt.AddressKey} has not been written by unidentified errors. ", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); LogMessage.MessageOutput.ConsoleWrite($" - Error Message: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); return false; } } public void WriteDevice(string strDevice) { int nCount = 0; if (!OperationStarted) { while (true) { if (OperationStarted || nCount > 100) break; nCount++; Thread.Sleep(100); } } PLCAddressTemplate tmplt = AddrMgr.FindPLCAddressElement(strDevice); WriteDevice(tmplt); } public bool WriteDevice(PLCAddressTemplate tmplt) { try { int nCount = 0; if (!OperationStarted) { while (true) { if (OperationStarted || nCount > 100) break; nCount++; Thread.Sleep(100); } } int nLength = Convert.ToInt32(tmplt.Length); if (nLength > 1) WriteBlockDevice(tmplt, nLength, tmplt.RawValue); else WriteDeviceSequence(tmplt, nLength, tmplt.RawValue); //UpdateValue(tmplt, false); return true; } catch (Exception ex) { LogMessage.MessageOutput.ConsoleWrite($"PLC Manager is failed to Write Device. The Address: {tmplt.AddressKey} has not been written by unidentified errors. ", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); LogMessage.MessageOutput.ConsoleWrite($" - Error Message: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); return false; } } bool WriteBlockDevice(PLCAddressTemplate tmplt, int nLength, List vnValues) { try { string strAddr = tmplt.Area + (Convert.ToInt32(tmplt.Address)).ToString(); bool result = PLCManagers[ePLCRWType.Write].WriteBlockDevice(strAddr, vnValues.Count, vnValues.ToArray()); return result; /* if (result) { int[] anResult = PLCManagers[ePLCRWType.Read].ReadBlockDevice(strAddr, nLength); for(int nIdx = 0; nIdx < vnValues.Count; nIdx++) if (anResult[nIdx] != vnValues[nIdx]) { LogMessage.MessageOutput.ConsoleWrite($"During: WriteBlockDevice, The Address: {strAddr} + {nIdx} has not been written #Intent:{vnValues[nIdx]} - #Actual:{anResult[nIdx]} by unidentified errors. ", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE); return false; } } */ } catch (Exception ex) { LogMessage.MessageOutput.ConsoleWrite($"During: WriteBlockDevice, PLC Manager is failed to Write Device. The Address: {tmplt.AddressKey} has not been written by unidentified errors. ", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); LogMessage.MessageOutput.ConsoleWrite($" - Error Message: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); return false; } } bool WriteDeviceSequence(PLCAddressTemplate tmplt, int nLength, List vnValues) { try { for (int i = 0; i < nLength; i++) { //LogMessage.MessageOutput.ConsoleWrite($"The Address: {tmplt.AddressKey}. ", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE); string strAddr = tmplt.Area + (Convert.ToInt32(tmplt.Address) + i).ToString(); bool result = PLCManagers[ePLCRWType.Write].WriteDevice(strAddr, vnValues[i]); return result; /* if (i >= vnValues.Count) PLCManagers[ePLCRWType.Write].WriteDevice(strAddr, 0); else { bool result = PLCManagers[ePLCRWType.Write].WriteDevice(strAddr, vnValues[i]); return result; if (result) { int nResult = PLCManagers[ePLCRWType.Read].ReadDevice(strAddr); if (nResult != vnValues[i]) { LogMessage.MessageOutput.ConsoleWrite($"During: WriteDeviceSequence, The Address: {strAddr} has not been written #Intent:{vnValues[i]} - #Actual:{nResult} by unidentified errors. ", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE); return false; } } }*/ } } catch (Exception ex) { LogMessage.MessageOutput.ConsoleWrite($"During: WriteDeviceSequence, PLC Manager is failed to Write Device. The Address: {tmplt.AddressKey} has not been written by unidentified errors. ", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); LogMessage.MessageOutput.ConsoleWrite($" - Error Message: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL); return false; } return true; } List GetWriteValues(PLCAddressTemplate tmplt) { List vnValues = new List(); int nLength = Convert.ToInt32(tmplt.Length); eDataType eType = (eDataType)Enum.Parse(typeof(eDataType), tmplt.DataType); if (eType == eDataType.ASCII) vnValues = (from value in CommonUtil.HexStringToBytes(tmplt.Value) select Convert.ToInt32(value)).ToList(); else if (eType == eDataType.DECIMAL) { int nInputValue = string.IsNullOrWhiteSpace(tmplt.Value) ? 0 : Convert.ToInt32(tmplt.Value); vnValues.Add(nInputValue); } return vnValues; } List GetReadValues(PLCAddressTemplate tmplt) { List vnValues = new List(); int nLength = Convert.ToInt32(tmplt.Length); /* for (int i = 0; i < nLength; i++) { int nAddress = Convert.ToInt32(tmplt.Address) + i; int nValue = PLCManagers[ePLCRWType.Read].ReadDevice(tmplt.Area + nAddress.ToString()); vnValues.Add(nValue); } */ if (nLength > 1) { int[] anResult = PLCManagers[ePLCRWType.Read].ReadBlockDevice(tmplt.PLCAddress, nLength); if (anResult != null) vnValues = anResult.ToList(); } else { for (int i = 0; i < nLength; i++) { int nAddress = Convert.ToInt32(tmplt.Address) + i; int nValue = PLCManagers[ePLCRWType.Read].ReadDevice(tmplt.Area + nAddress.ToString()); vnValues.Add(nValue); } } return vnValues; } } }