[성현모] CPXV2 Init
This commit is contained in:
@ -0,0 +1,497 @@
|
||||
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<ePLCRWType, PLCModMxCMgr> PLCManagers { get; set; } = new Dictionary<ePLCRWType, PLCModMxCMgr>();
|
||||
|
||||
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<bool> openconn = new Task<bool>(() => TryOpenPLCConnection());
|
||||
|
||||
openconn.Start();
|
||||
|
||||
bool bResult = openconn.Result;
|
||||
|
||||
if (bResult)
|
||||
{
|
||||
//Task plcoperation = openconn.ContinueWith(x => StartPLCOperation());
|
||||
Task<bool> plcoperation = new Task<bool>(() => 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<string, PLCAddressTemplate> 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<int> 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<string> 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<int> 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<int> 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<int> GetWriteValues(PLCAddressTemplate tmplt)
|
||||
{
|
||||
List<int> vnValues = new List<int>();
|
||||
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<int> GetReadValues(PLCAddressTemplate tmplt)
|
||||
{
|
||||
List<int> vnValues = new List<int>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,157 @@
|
||||
using Dsu.PLC;
|
||||
using Dsu.PLC.Common;
|
||||
using Dsu.PLC.Melsec;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using SystemX.Net.Platform.Common.Event;
|
||||
using SystemX.Net.Platform.Common.Util;
|
||||
|
||||
namespace SystemX.PLC.Interface.McProtocol
|
||||
{
|
||||
public class PLCDeviceMXC
|
||||
{
|
||||
public FunctionEventHandler FuncEvtHndl { get; set; }
|
||||
public string CPU_TYPE_STR { set; get; } //Example: "Q03UDECPU";
|
||||
public string PLC_IP_ADDR { set; get; }
|
||||
public int PLC_PORT_NUMBER { set; get; }
|
||||
public string CONNECTION_TYPE_STR { set; get; }
|
||||
public int TIMEOUT { set; get; }
|
||||
public bool READPORT { set; get; }
|
||||
public string DeviceID { set; get; }
|
||||
|
||||
private MxConnection _conn; // Read port UDP Write port TCP
|
||||
|
||||
public bool DevClose()
|
||||
{
|
||||
return _conn.Disconnect();
|
||||
}
|
||||
|
||||
public bool DevOpen()
|
||||
{
|
||||
try
|
||||
{
|
||||
TransportProtocol ConType = CONNECTION_TYPE_STR.ToUpper() == "TCP" ? TransportProtocol.Tcp : TransportProtocol.Udp;
|
||||
_conn = new MxConnection(new MxConnectionParameters(PLC_IP_ADDR, Convert.ToUInt16(PLC_PORT_NUMBER), ConType));
|
||||
return _conn.Connect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite(ex.Message, ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AddDevices(string deviceNames)
|
||||
{
|
||||
_conn.CreateTag(deviceNames);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task SingleScanStartAsync()
|
||||
{
|
||||
if (_conn.Tags.Count == 0)
|
||||
return;
|
||||
|
||||
int readCount = 0;
|
||||
|
||||
_conn.PerRequestDelay = TIMEOUT;
|
||||
|
||||
_conn.Subject.OfType<TagValueChangedEvent>().Subscribe(evt =>
|
||||
{
|
||||
readCount++;
|
||||
EventTag((MxTag)evt.Tag);
|
||||
});
|
||||
|
||||
_conn.StartDataExchangeLoopAsync(); // Do not use await
|
||||
|
||||
// _conn.Disconnect();
|
||||
|
||||
Stopwatch xSW = new Stopwatch();
|
||||
xSW.Start();
|
||||
bool bSuccess = true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (_conn.Tags.Count <= readCount)
|
||||
break;
|
||||
else
|
||||
System.Threading.Thread.Sleep(50);
|
||||
|
||||
if (xSW.ElapsedMilliseconds > 5000)
|
||||
{
|
||||
bSuccess = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bSuccess)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite("Trouble in Single Scan Start Async", ConsoleColor.White, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
//await SingleScanStartAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private void EventTag(MxTag tag)
|
||||
{
|
||||
if (tag.IsBitDevice)
|
||||
FuncEvtHndl.DoReceive(this, tag.Name + ";" + (Convert.ToBoolean(tag.Value) ? 1 : 0).ToString());
|
||||
else
|
||||
FuncEvtHndl.DoReceive(this, tag.Name + ";" + tag.Value.ToString());
|
||||
}
|
||||
|
||||
public bool WriteBitDevice(string strDeviceWrite, int[] value)
|
||||
{
|
||||
//Console.WriteLine(string.Format("{0} : {1}", strDeviceWrite, value[0]));
|
||||
return _conn.McProtocol.SetBitDevice(strDeviceWrite, 1, value) == 0;
|
||||
}
|
||||
|
||||
public bool WriteDevice(string strDeviceWrite, int value)
|
||||
{
|
||||
//Console.WriteLine(string.Format("{0} : {1}", strDeviceWrite, value));
|
||||
return _conn.McProtocol.SetDevice(strDeviceWrite, Convert.ToInt32(value)) == 0;
|
||||
}
|
||||
|
||||
public bool WriteBlockDevice(string strDeviceWrite, int nLength, int[] nValues)
|
||||
{
|
||||
//Console.WriteLine(string.Format("{0} : {1}", strDeviceWrite, value));
|
||||
return _conn.McProtocol.WriteDeviceBlock(strDeviceWrite, nLength, nValues) == 0;
|
||||
}
|
||||
|
||||
public int ReadDevice(string strDeviceRead)
|
||||
{
|
||||
int value;
|
||||
_conn.McProtocol.GetDevice(strDeviceRead, out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public int[] ReadBlockDevice(string strDeviceRead, int nLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
int[] anvalue = new int[nLength];
|
||||
|
||||
int nResult = _conn.McProtocol.ReadDeviceBlock(strDeviceRead, nLength, anvalue);
|
||||
|
||||
return anvalue;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"Trouble in McComponent during ReadBlockDevice:{strDeviceRead} - {nLength}", ConsoleColor.White, LogMessage.LogMessageLevel.FATAL);
|
||||
LogMessage.MessageOutput.ConsoleWrite($"\t- Error Message {ex.Message}", ConsoleColor.White, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
return new int[1];
|
||||
}
|
||||
}
|
||||
public string GetModuleName()
|
||||
{
|
||||
return Assembly.GetExecutingAssembly().ManifestModule.Name.Replace(".dll", string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,199 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Threading;
|
||||
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 PLCModMxCMgr
|
||||
{
|
||||
public event EventPLCHandler EventPLC;
|
||||
public FunctionEventHandler EventAlwaysUpdate { get; set; }
|
||||
public FunctionEventHandler EventChangeUpdate { get; set; }
|
||||
public PLCDeviceMXC plcDev;
|
||||
|
||||
PLCConnectionInfo PLCInfo;
|
||||
|
||||
public string CPU_TYPE_STR { set; get; } //Example: "Q03UDECPU";
|
||||
public string PLC_IP_ADDR { set; get; }
|
||||
public int PLC_PORT_NUMBER { set; get; }
|
||||
public string CONNECTION_TYPE_STR { set; get; }
|
||||
public int TIMEOUT { set; get; }
|
||||
public bool IsOpened { get; set; } = false;
|
||||
|
||||
public PLCModMxCMgr(PLCConnectionInfo infoinput)
|
||||
{
|
||||
PLCInfo = infoinput;
|
||||
}
|
||||
|
||||
public bool CloseDevice()
|
||||
{
|
||||
bool bResult = plcDev.DevClose();
|
||||
|
||||
IsOpened = !bResult;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OpenDevice()
|
||||
{
|
||||
if (IsOpened == true)
|
||||
return IsOpened;
|
||||
|
||||
plcDev = new PLCDeviceMXC();
|
||||
EventChangeUpdate = new FunctionEventHandler();
|
||||
|
||||
plcDev.FuncEvtHndl = EventChangeUpdate;
|
||||
plcDev.DeviceID = PLCInfo.Name;
|
||||
plcDev.CPU_TYPE_STR = PLCInfo.CPUType;
|
||||
plcDev.PLC_IP_ADDR = PLCInfo.IP;
|
||||
plcDev.PLC_PORT_NUMBER = Convert.ToInt32(PLCInfo.Port);
|
||||
plcDev.CONNECTION_TYPE_STR = PLCInfo.ConnectionType != "UDP" ? "TCP" : "UDP";
|
||||
plcDev.READPORT = (PLCInfo.RWType == PLCCommDefinition.ePLCRWType.Read.ToString()) ? true : false;
|
||||
plcDev.TIMEOUT = Convert.ToInt32(PLCInfo.Timeout);
|
||||
|
||||
EventChangeUpdate.OnReceive += FuncEvtHndl_OnPLCReceive;
|
||||
|
||||
Task<bool> conPing = new Task<bool>(() => PingToPLC());
|
||||
|
||||
conPing.Start();
|
||||
|
||||
Task<bool> conPLC = conPing.ContinueWith(x => ConnectToPLC());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool PingToPLC()
|
||||
{
|
||||
try
|
||||
{
|
||||
Ping pingtoPLC = new Ping();
|
||||
int nCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
PingReply reply = pingtoPLC.Send(plcDev.PLC_IP_ADDR);
|
||||
|
||||
if (reply.Status == IPStatus.Success)
|
||||
break;
|
||||
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Connection Failed. Retry #{nCount} - IP:{plcDev.PLC_IP_ADDR}, Port:{plcDev.PLC_PORT_NUMBER}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
Thread.Sleep(1000);
|
||||
nCount++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - PLC Connection error: {PLCInfo.Name}, {PLCInfo.IP}:{PLCInfo.Port} - {PLCInfo.ConnectionType}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" -> Reason: {ex.Message}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ConnectToPLC()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
IsOpened = plcDev.DevOpen();
|
||||
|
||||
if (IsOpened == false)
|
||||
plcDev = null;
|
||||
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Connection Success. - IP:{plcDev.PLC_IP_ADDR}, Port:{plcDev.PLC_PORT_NUMBER} ", ConsoleColor.Green, LogMessage.LogMessageLevel.NONE);
|
||||
|
||||
return IsOpened;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - PLC Connection error: {PLCInfo.Name}, {PLCInfo.IP}:{PLCInfo.Port} - {PLCInfo.ConnectionType}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" -> Reason: {ex.Message}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void FuncEvtHndl_OnPLCReceive(object sender, object objdata)
|
||||
{
|
||||
string data = objdata as string;
|
||||
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
if (data.Contains(";"))
|
||||
{
|
||||
string address = data.Split(';')[0];
|
||||
int value = Convert.ToInt32(data.Split(';')[1]);
|
||||
|
||||
EventPLC?.Invoke(address, value);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SingleScanStartAsync()
|
||||
{
|
||||
if (!IsOpened) return;
|
||||
|
||||
await plcDev.SingleScanStartAsync();
|
||||
}
|
||||
|
||||
public bool AddDevices(string deviceNames)
|
||||
{
|
||||
if (!IsOpened) return false;
|
||||
|
||||
return plcDev.AddDevices(deviceNames);
|
||||
}
|
||||
|
||||
public int ReadDevice(string deviceName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsOpened) return -1;
|
||||
return plcDev.ReadDevice(deviceName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Device Reading Error in PLCModMxCMgr: {deviceName}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - Detail: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] ReadBlockDevice(string deviceName, int nLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsOpened) return null;
|
||||
return plcDev.ReadBlockDevice(deviceName, nLength);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Device Reading Error in PLCModMxCMgr: {deviceName}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - Detail: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public bool WriteDevice(string deviceName, int value)
|
||||
{
|
||||
if (!IsOpened) return false;
|
||||
return plcDev.WriteDevice(deviceName, value);
|
||||
}
|
||||
|
||||
public bool WriteBlockDevice(string deviceName, int nLength, int[] aValues)
|
||||
{
|
||||
if (!IsOpened) return false;
|
||||
return plcDev.WriteBlockDevice(deviceName, nLength, aValues);
|
||||
}
|
||||
|
||||
public bool WriteBitDevice(string deviceName, int[] value)
|
||||
{
|
||||
if (!IsOpened) return false;
|
||||
return plcDev.WriteBitDevice(deviceName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,420 @@
|
||||
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.MxComponent
|
||||
{
|
||||
public class PLCCommMxCMgr : PLCCommManager
|
||||
{
|
||||
private int TimeOut;
|
||||
|
||||
public Dictionary<ePLCRWType, PLCModMxCMgr> PLCManagers { get; set; } = new Dictionary<ePLCRWType, PLCModMxCMgr>();
|
||||
public FunctionEventHandler EventAlwaysUpdate { get; set; }
|
||||
|
||||
public PLCCommMxCMgr(string strPLCConnInfoXmlPath) : base(strPLCConnInfoXmlPath)
|
||||
{
|
||||
AddrMgr = new PLCAddressManager(strPLCConnInfoXmlPath);
|
||||
|
||||
EventAlwaysUpdate = new FunctionEventHandler();
|
||||
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, EventAlwaysUpdate, EventChangeUpdate));
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OpenPLCConnection()
|
||||
{
|
||||
Task<bool> openconn = new Task<bool>(() => TryOpenPLCConnection());
|
||||
|
||||
openconn.Start();
|
||||
|
||||
bool bResult = openconn.Result;
|
||||
|
||||
if (bResult)
|
||||
{
|
||||
//Task plcoperation = openconn.ContinueWith(x => StartPLCOperation());
|
||||
Task<bool> plcoperation = new Task<bool>(() => 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);
|
||||
}
|
||||
|
||||
SetAddress(conmgr, AddrMgr.OperationDictionary, true);
|
||||
SetAddress(conmgr, AddrMgr.DataDictionary, false);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private bool findType(ePLCRWType type)
|
||||
{
|
||||
var findValue = PLCManagers.FirstOrDefault(t => t.Key == type);
|
||||
|
||||
if (findValue.Value != null)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private PLCModMxCMgr findMgr(ePLCRWType type)
|
||||
{
|
||||
var findValue = PLCManagers.FirstOrDefault(t => t.Key == type);
|
||||
|
||||
if (findValue.Value != null)
|
||||
return findValue.Value;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool StartPLCOperation()
|
||||
{
|
||||
try
|
||||
{
|
||||
OperationStarted = true;
|
||||
|
||||
if(findType(ePLCRWType.Read))
|
||||
{
|
||||
findMgr(ePLCRWType.Read).SingleScanStartAsync();
|
||||
findMgr(ePLCRWType.Read).StartMonitor();
|
||||
}
|
||||
if (findType(ePLCRWType.ReadWrite))
|
||||
{
|
||||
findMgr(ePLCRWType.ReadWrite).SingleScanStartAsync();
|
||||
findMgr(ePLCRWType.ReadWrite).StartMonitor();
|
||||
}
|
||||
|
||||
LogMessage.MessageOutput.ConsoleWrite("PLC Operation has been 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()
|
||||
{
|
||||
if (findType(ePLCRWType.Read))
|
||||
findMgr(ePLCRWType.Read).NowScanDataArea();
|
||||
if (findType(ePLCRWType.ReadWrite))
|
||||
findMgr(ePLCRWType.ReadWrite).NowScanDataArea();
|
||||
}
|
||||
|
||||
public override bool StopPLCOperation()
|
||||
{
|
||||
try
|
||||
{
|
||||
OperationStarted = false;
|
||||
|
||||
if (findType(ePLCRWType.Read))
|
||||
findMgr(ePLCRWType.Read).StopMonitor();
|
||||
if (findType(ePLCRWType.ReadWrite))
|
||||
findMgr(ePLCRWType.ReadWrite).StopMonitor();
|
||||
|
||||
LogMessage.MessageOutput.ConsoleWrite("PLC Operation has been Stopped.", 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 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 void ReceivePLCEvent(PLCModMxCMgr sender, PLCAddressTemplate template)
|
||||
{
|
||||
if (template == null)
|
||||
return;
|
||||
|
||||
if (IsMySubscription(template))
|
||||
{
|
||||
ReceivePLCEvent(template.Address, template.RawValue[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ReceivePLCEvent(string address, int value)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsMySubscription(PLCAddressTemplate template)
|
||||
{
|
||||
if (AddrMgr.OperationDictionary.ContainsValue(template))
|
||||
return true;
|
||||
if (AddrMgr.DataDictionary.ContainsValue(template))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetAddress(PLCModMxCMgr module, Dictionary<string, PLCAddressTemplate> addressInfo, bool bOperation)
|
||||
{
|
||||
foreach (PLCAddressTemplate addrinfo in addressInfo.Values)
|
||||
module.AddDevices(addrinfo, bOperation);
|
||||
}
|
||||
|
||||
public override void UpdateAll(bool bRefineWrongChar)
|
||||
{
|
||||
foreach (PLCModMxCMgr conmgr in PLCManagers.Values)
|
||||
{
|
||||
conmgr.UpdateArea(AddrMgr.OperationDictionary.Values.ToList(), bRefineWrongChar);
|
||||
conmgr.UpdateArea(AddrMgr.DataDictionary.Values.ToList(), bRefineWrongChar);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SelectUpdate(ePLCAreaType pat, PLCAddressTemplate tmplt, bool bRefineWrongChar)
|
||||
{
|
||||
if (pat == ePLCAreaType.Operation)
|
||||
{
|
||||
foreach (PLCModMxCMgr conmgr in PLCManagers.Values)
|
||||
{
|
||||
conmgr.UpdateSelectArea(tmplt, bRefineWrongChar);
|
||||
//conmgr.UpdateArea(AddrMgr.DataDictionary.Values.ToList(), bRefineWrongChar);
|
||||
}
|
||||
}
|
||||
if (pat == ePLCAreaType.Data)
|
||||
{
|
||||
foreach (PLCModMxCMgr conmgr in PLCManagers.Values)
|
||||
{
|
||||
//conmgr.UpdateArea(AddrMgr.OperationDictionary.Values.ToList(), bRefineWrongChar);
|
||||
conmgr.UpdateSelectArea(tmplt, bRefineWrongChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetDeviceValue(PLCAddressTemplate tmplt)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!CheckConnectionState(tmplt))
|
||||
return string.Empty;
|
||||
|
||||
string strReadValue = "";
|
||||
|
||||
if (findType(ePLCRWType.Read))
|
||||
strReadValue = findMgr(ePLCRWType.Read).GetDeviceValue(tmplt);
|
||||
else if (findType(ePLCRWType.ReadWrite))
|
||||
strReadValue = findMgr(ePLCRWType.ReadWrite).GetDeviceValue(tmplt);
|
||||
|
||||
return strReadValue;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Manager is failed to Get Device Value. 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 string ReadDevice(PLCAddressTemplate tmplt)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!CheckConnectionState(tmplt))
|
||||
return string.Empty;
|
||||
|
||||
string strReadValue = "";
|
||||
|
||||
if (findType(ePLCRWType.Read))
|
||||
strReadValue = findMgr(ePLCRWType.Read).ReadDevice(tmplt);
|
||||
else if (findType(ePLCRWType.ReadWrite))
|
||||
strReadValue = findMgr(ePLCRWType.ReadWrite).ReadDevice(tmplt);
|
||||
|
||||
return strReadValue;
|
||||
}
|
||||
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 string ReadDevice(PLCAddressTemplate tmplt, bool bAsciiReverse = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!CheckConnectionState(tmplt))
|
||||
return string.Empty;
|
||||
|
||||
string strReadValue = "";
|
||||
|
||||
if (findType(ePLCRWType.Read))
|
||||
strReadValue = findMgr(ePLCRWType.Read).ReadDevice(tmplt, bAsciiReverse);
|
||||
else if (findType(ePLCRWType.ReadWrite))
|
||||
strReadValue = findMgr(ePLCRWType.ReadWrite).ReadDevice(tmplt, bAsciiReverse);
|
||||
|
||||
return strReadValue;
|
||||
}
|
||||
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 bool WriteDevice(PLCAddressTemplate tmplt, string strValue, bool bVerification = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!CheckConnectionState(tmplt))
|
||||
return false;
|
||||
|
||||
if (findType(ePLCRWType.Write))
|
||||
findMgr(ePLCRWType.Write).WriteDevice(tmplt, strValue);
|
||||
else if (findType(ePLCRWType.ReadWrite))
|
||||
findMgr(ePLCRWType.ReadWrite).WriteDevice(tmplt, strValue);
|
||||
|
||||
if (bVerification)
|
||||
{
|
||||
string strReadValue = "";
|
||||
|
||||
if (findType(ePLCRWType.Read))
|
||||
strReadValue = findMgr(ePLCRWType.Read).ReadDevice(tmplt);
|
||||
else if (findType(ePLCRWType.ReadWrite))
|
||||
strReadValue = findMgr(ePLCRWType.ReadWrite).ReadDevice(tmplt);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckConnectionState(PLCAddressTemplate tmplt)
|
||||
{
|
||||
try
|
||||
{
|
||||
int nCount = 0;
|
||||
bool bConError = false;
|
||||
if (!OperationStarted)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (OperationStarted || nCount > 100)
|
||||
{
|
||||
bConError = true;
|
||||
break;
|
||||
}
|
||||
|
||||
nCount++;
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
if (bConError == true)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Connection Trouble has been detected. ", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
LogMessage.MessageOutput.ConsoleWrite($"The Address: {tmplt.PLCAddress} has not been written. ", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,314 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reflection;
|
||||
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.MxComponent
|
||||
{
|
||||
public class PLCDeviceMXC
|
||||
{
|
||||
public FunctionEventHandler EventAlwaysUpdate { get; set; }
|
||||
public FunctionEventHandler EventChangeUpdate { get; set; }
|
||||
|
||||
public int STATION_ID { set; get; } //PLC STATION
|
||||
|
||||
private int ScanningIntervalOperation = 100;
|
||||
private int ScanningIntervalDataTime = 500;
|
||||
|
||||
private bool MonitorExe = true;
|
||||
|
||||
private Stopwatch stReadTimeCheck;
|
||||
|
||||
private PLCMxComponent _conn; //MxComponent PLC Instance
|
||||
|
||||
Dictionary<string, PLCAddressTemplate> DicOperationAddresses = new Dictionary<string, PLCAddressTemplate>();
|
||||
Dictionary<string, PLCAddressTemplate> DicDataAddresses = new Dictionary<string, PLCAddressTemplate>();
|
||||
|
||||
Stopwatch xSwDiag = new Stopwatch();
|
||||
|
||||
private static object objLock = new object();
|
||||
|
||||
public PLCDeviceMXC()
|
||||
{
|
||||
stReadTimeCheck = new Stopwatch();
|
||||
stReadTimeCheck.Start();
|
||||
}
|
||||
|
||||
public bool DevClose()
|
||||
{
|
||||
if (_conn != null)
|
||||
{
|
||||
StopMonitor();
|
||||
|
||||
return _conn.Close();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DevOpen()
|
||||
{
|
||||
try
|
||||
{
|
||||
_conn = new PLCMxComponent();
|
||||
|
||||
_conn.Initialize();
|
||||
|
||||
return _conn.Open(STATION_ID.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"Error during PLC Open : {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AddOperationDevices(PLCAddressTemplate deviceReg)
|
||||
{
|
||||
DicOperationAddresses.Add(deviceReg.PLCAddress, deviceReg);
|
||||
|
||||
return true;
|
||||
}
|
||||
public bool AddDataDevices(PLCAddressTemplate deviceReg)
|
||||
{
|
||||
DicDataAddresses.Add(deviceReg.PLCAddress, deviceReg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SingleScanStartAsync()
|
||||
{
|
||||
lock (objLock)
|
||||
{
|
||||
ScanDataArea();
|
||||
|
||||
ScanOperationArea(true);
|
||||
}
|
||||
}
|
||||
public void NowDataAreaScan()
|
||||
{
|
||||
lock (objLock)
|
||||
{
|
||||
ScanDataArea();
|
||||
}
|
||||
}
|
||||
public void StartMonitor()
|
||||
{
|
||||
MonitorExe = true;
|
||||
|
||||
Task<int> monitor = new Task<int>(() => ExecuteMonitor().Result);
|
||||
|
||||
monitor.Start();
|
||||
}
|
||||
|
||||
public void StopMonitor()
|
||||
{
|
||||
MonitorExe = false;
|
||||
}
|
||||
|
||||
private async Task<int> ExecuteMonitor()
|
||||
{
|
||||
//int nCountTime = 0;
|
||||
|
||||
stReadTimeCheck.Restart();
|
||||
|
||||
while (MonitorExe)
|
||||
{
|
||||
lock (objLock)
|
||||
{
|
||||
ScanOperationArea();
|
||||
|
||||
/*
|
||||
if (stReadTimeCheck.ElapsedMilliseconds >= ScanningIntervalDataTime)
|
||||
{
|
||||
ScanDataArea();
|
||||
|
||||
stReadTimeCheck.Restart();
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
|
||||
/*
|
||||
if (nCountTime % ScanningIntervalDataTime == 0)
|
||||
{
|
||||
nCountTime = 1;
|
||||
|
||||
ScanDataArea();
|
||||
}
|
||||
|
||||
nCountTime++;
|
||||
*/
|
||||
}
|
||||
|
||||
await Task.Delay(ScanningIntervalOperation);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ScanDataArea()
|
||||
{
|
||||
foreach (PLCAddressTemplate addrTemplate in DicDataAddresses.Values)
|
||||
UpdateDevice(addrTemplate, true);
|
||||
}
|
||||
|
||||
void ScanOperationArea(bool bSingleScan = false)
|
||||
{
|
||||
foreach (PLCAddressTemplate addrTemplate in DicOperationAddresses.Values)
|
||||
{
|
||||
string strFormerValue = addrTemplate.Value;
|
||||
|
||||
UpdateDevice(addrTemplate, true);
|
||||
|
||||
EventAlwaysUpdate.DoReceive(this, addrTemplate);
|
||||
|
||||
if (addrTemplate.Value != strFormerValue)
|
||||
EventChangeUpdate.DoReceive(this, addrTemplate);
|
||||
|
||||
if (bSingleScan)
|
||||
EventChangeUpdate.DoReceive(this, addrTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetModuleName()
|
||||
{
|
||||
return Assembly.GetExecutingAssembly().ManifestModule.Name.Replace(".dll", string.Empty);
|
||||
}
|
||||
|
||||
Int16[] ReadPLCData(PLCAddressTemplate template)
|
||||
{
|
||||
if (_conn == null)
|
||||
return null;
|
||||
|
||||
int nSize = Convert.ToInt32(template.Length);
|
||||
|
||||
Int16[] readData = new Int16[nSize];
|
||||
|
||||
_conn.BlockReadData(template.PLCAddress, nSize, ref readData);
|
||||
|
||||
return readData;
|
||||
}
|
||||
|
||||
bool WritePLCData(PLCAddressTemplate template, Int16[] arnWriteData)
|
||||
{
|
||||
if (_conn == null)
|
||||
return false;
|
||||
|
||||
int nSize = Convert.ToInt32(template.Length);
|
||||
|
||||
bool ret = _conn.BlockWriteData(template.PLCAddress, nSize, arnWriteData);
|
||||
|
||||
if (ret == false)
|
||||
{
|
||||
_conn.BlockWriteData(template.PLCAddress, nSize, arnWriteData);
|
||||
|
||||
Thread.Sleep(30);
|
||||
}
|
||||
|
||||
Thread.Sleep(30);
|
||||
|
||||
//bool ret = PLC_COMM.WriteData(addr, nSize, arnWriteData);
|
||||
return ret;
|
||||
}
|
||||
|
||||
List<int> GetReadValues(PLCAddressTemplate tmplt)
|
||||
{
|
||||
int nLength = Convert.ToInt32(tmplt.Length);
|
||||
|
||||
List<int> vnValues = (from value in ReadPLCData(tmplt) let value32 = Convert.ToInt32(value) select value32).ToList();
|
||||
|
||||
return vnValues;
|
||||
}
|
||||
|
||||
List<short> GetWriteValues(PLCAddressTemplate tmplt, string strValue)
|
||||
{
|
||||
List<short> vnValues = new List<short>();
|
||||
|
||||
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(strValue) select Convert.ToInt16(value)).ToList();
|
||||
else if (eType == eDataType.DECIMAL)
|
||||
{
|
||||
int nInputValue = string.IsNullOrWhiteSpace(strValue) ? 0 : Convert.ToInt16(strValue);
|
||||
vnValues.Add(Convert.ToInt16(nInputValue));
|
||||
}
|
||||
|
||||
return vnValues;
|
||||
}
|
||||
|
||||
void UpdateValue(PLCAddressTemplate tmplt, bool bRefineWrongChar, bool bAsciiReverseBit = false)
|
||||
{
|
||||
List<int> vValues = GetReadValues(tmplt);
|
||||
|
||||
eDataType eType = (eDataType)Enum.Parse(typeof(eDataType), tmplt.DataType);
|
||||
|
||||
string strData = string.Empty;
|
||||
|
||||
if (eType == eDataType.ASCII)
|
||||
strData = CommonUtil.GetStringFromASCII(vValues.ToArray(), bAsciiReverseBit);
|
||||
else if (eType == eDataType.BIT)
|
||||
strData = vValues[0].ToString();
|
||||
else if (eType == eDataType.DECIMAL)
|
||||
strData = vValues[0].ToString();
|
||||
|
||||
string strResult = bRefineWrongChar ? RefineInvalidChars(strData) : strData;
|
||||
|
||||
tmplt.SetStringValue(strResult);
|
||||
}
|
||||
|
||||
string RefineInvalidChars(string strSource)
|
||||
{
|
||||
string strReturn = strSource.Trim(InvalidChars);
|
||||
|
||||
strReturn = new string((from cCode in strSource.ToCharArray() where (48 <= Convert.ToInt32(cCode) && Convert.ToInt32(cCode) <= 95) select cCode).ToArray());
|
||||
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
public string GetDeviceValue(PLCAddressTemplate tmplt)
|
||||
{
|
||||
List<PLCAddressTemplate> Oper = DicOperationAddresses.Values.Where(x => x.DataName == tmplt.DataName).ToList();
|
||||
List<PLCAddressTemplate> Data = DicDataAddresses.Values.Where(x => x.DataName == tmplt.DataName).ToList();
|
||||
|
||||
if (Oper.Count > 0)
|
||||
return Oper.First().Value;
|
||||
else if (Data.Count > 0)
|
||||
return Data.First().Value;
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public PLCAddressTemplate UpdateDevice(PLCAddressTemplate tmplt, bool bRefineWrongChar, bool bAsciiReverse = false)
|
||||
{
|
||||
if (tmplt == null)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"Cannot Find a Corresponding Data.");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
UpdateValue(tmplt, bRefineWrongChar, bAsciiReverse);
|
||||
|
||||
return tmplt;
|
||||
}
|
||||
|
||||
public bool WriteDevice(PLCAddressTemplate tmplt, string strValue)
|
||||
{
|
||||
List<short> vValues = GetWriteValues(tmplt, strValue);
|
||||
|
||||
return WritePLCData(tmplt, vValues.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,228 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Threading;
|
||||
using SystemX.Net.Platform.Common.Event;
|
||||
using SystemX.Net.Platform.Common.Util;
|
||||
|
||||
namespace SystemX.PLC.Interface.MxComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Example to represent how to build a device manager.
|
||||
/// A Device Manager constructs a device in run-time environment using a defined dll name in the configuration xml.
|
||||
/// The named dll for a device is bound in run-time environment as well.
|
||||
/// Device manager is an inherited class from a CpDeviceManagerBase and a corresponding interface.
|
||||
/// </summary>
|
||||
public class PLCModMxCMgr
|
||||
{
|
||||
public FunctionEventHandler EventAlwaysUpdate { get; set; }
|
||||
public FunctionEventHandler EventChangeUpdate { get; set; }
|
||||
public PLCDeviceMXC plcMXCompDev;
|
||||
public PLCConnectionInfo PLCInfo;
|
||||
|
||||
public bool IsOpened { get; set; } = false;
|
||||
|
||||
public PLCModMxCMgr(PLCConnectionInfo infoinput, FunctionEventHandler evtHndlAlways, FunctionEventHandler evtHndlChanges)
|
||||
{
|
||||
PLCInfo = infoinput;
|
||||
|
||||
EventAlwaysUpdate = evtHndlAlways;
|
||||
EventChangeUpdate = evtHndlChanges;
|
||||
}
|
||||
|
||||
public bool CloseDevice()
|
||||
{
|
||||
if (plcMXCompDev == null)
|
||||
return true;
|
||||
|
||||
bool bResult = plcMXCompDev.DevClose();
|
||||
|
||||
IsOpened = !bResult;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OpenDevice()
|
||||
{
|
||||
if (IsOpened == true)
|
||||
return IsOpened;
|
||||
|
||||
plcMXCompDev = new PLCDeviceMXC();
|
||||
|
||||
plcMXCompDev.STATION_ID = Convert.ToInt32(PLCInfo.Port);
|
||||
plcMXCompDev.EventAlwaysUpdate = EventAlwaysUpdate;
|
||||
plcMXCompDev.EventChangeUpdate = EventChangeUpdate;
|
||||
|
||||
Task<bool> conPing = new Task<bool>(() => PingToPLC());
|
||||
|
||||
conPing.Start();
|
||||
|
||||
Task<bool> conPLC = conPing.ContinueWith(x => ConnectToPLC());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool PingToPLC()
|
||||
{
|
||||
try
|
||||
{
|
||||
Ping pingtoPLC = new Ping();
|
||||
int nCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
PingReply reply = pingtoPLC.Send(PLCInfo.IP);
|
||||
|
||||
if (reply.Status == IPStatus.Success)
|
||||
break;
|
||||
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Connection Failed. Retry #{nCount} - IP:{PLCInfo.IP}, Station ID:{PLCInfo.Port}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
Thread.Sleep(1000);
|
||||
|
||||
nCount++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - PLC Connection error: {PLCInfo.Name}, {PLCInfo.IP}:{PLCInfo.Port} - {PLCInfo.ConnectionType}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" -> Reason: {ex.Message}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ConnectToPLC()
|
||||
{
|
||||
try
|
||||
{
|
||||
IsOpened = plcMXCompDev.DevOpen();
|
||||
|
||||
if (IsOpened == false)
|
||||
plcMXCompDev = null;
|
||||
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Connection Success. - IP:{PLCInfo.IP}, Port:{PLCInfo.Port} ", ConsoleColor.Green, LogMessage.LogMessageLevel.NONE);
|
||||
|
||||
return IsOpened;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - PLC Connection error: {PLCInfo.Name}, {PLCInfo.IP}:{PLCInfo.Port} - {PLCInfo.ConnectionType}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" -> Reason: {ex.Message}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void SingleScanStartAsync()
|
||||
{
|
||||
if (!IsOpened) return;
|
||||
|
||||
plcMXCompDev.SingleScanStartAsync();
|
||||
}
|
||||
|
||||
public void NowScanDataArea()
|
||||
{
|
||||
if (!IsOpened) return;
|
||||
|
||||
plcMXCompDev.NowDataAreaScan();
|
||||
}
|
||||
|
||||
public void StartMonitor()
|
||||
{
|
||||
plcMXCompDev.StartMonitor();
|
||||
}
|
||||
|
||||
public void StopMonitor()
|
||||
{
|
||||
plcMXCompDev.StopMonitor();
|
||||
}
|
||||
|
||||
public bool AddDevices(PLCAddressTemplate deviceReg, bool bOperation)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsOpened) return false;
|
||||
|
||||
if (bOperation)
|
||||
plcMXCompDev.AddOperationDevices(deviceReg);
|
||||
else
|
||||
plcMXCompDev.AddDataDevices(deviceReg);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - PLC Connection AddDevices: {PLCInfo.Name}, {PLCInfo.IP}:{PLCInfo.Port} - {PLCInfo.ConnectionType}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" -> Reason: {ex.Message}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateArea(List<PLCAddressTemplate> vTemplates, bool bRefineWrongChar)
|
||||
{
|
||||
foreach (PLCAddressTemplate keyTemplate in vTemplates)
|
||||
plcMXCompDev.UpdateDevice(keyTemplate, bRefineWrongChar);
|
||||
}
|
||||
|
||||
public void UpdateSelectArea(PLCAddressTemplate keyTemplate, bool bRefineWrongChar)
|
||||
{
|
||||
plcMXCompDev.UpdateDevice(keyTemplate, bRefineWrongChar);
|
||||
}
|
||||
|
||||
public string GetDeviceValue(PLCAddressTemplate tmplt)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsOpened) return string.Empty;
|
||||
|
||||
return plcMXCompDev.GetDeviceValue(tmplt);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Device Get Value Error: {tmplt.PLCAddress}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - Detail: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public string ReadDevice(PLCAddressTemplate tmplt, bool bAsciiReverse = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsOpened) return string.Empty;
|
||||
|
||||
plcMXCompDev.UpdateDevice(tmplt, true, bAsciiReverse);
|
||||
|
||||
return tmplt.Value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Device Reading Error: {tmplt.PLCAddress}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - Detail: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public bool WriteDevice(PLCAddressTemplate tmplt, string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsOpened) return false;
|
||||
|
||||
return plcMXCompDev.WriteDevice(tmplt, value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Device Writting Error: {tmplt.PLCAddress}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - Detail: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,222 @@
|
||||
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using SystemX.Net.Platform.Common.Util;
|
||||
|
||||
using ActUtlTypeLib;
|
||||
//using MITSUBISHI.Component;
|
||||
|
||||
namespace SystemX.PLC.Interface.MxComponent
|
||||
{
|
||||
class PLCMxComponent
|
||||
{
|
||||
//DotUtlType _DotUtlType;
|
||||
ActUtlTypeLib.ActUtlType _ActUtlType;
|
||||
|
||||
public bool m_IsPlcConnected;
|
||||
bool m_bLockFin = false;
|
||||
|
||||
// Set the read/write timeouts
|
||||
int m_nReadTimeOut = 500;
|
||||
int m_nWriteTimeOut = 500;
|
||||
|
||||
public PLCMxComponent()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SetTimeOut(int nWriteTimeOut, int nReadTimeOut)
|
||||
{
|
||||
m_nReadTimeOut = nReadTimeOut;
|
||||
m_nWriteTimeOut = nWriteTimeOut;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ActUtlType = new ActUtlTypeLib.ActUtlType();
|
||||
//_DotUtlType = new DotUtlType();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error in Initialization for plc: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Open(string localStationNum)
|
||||
{
|
||||
int lRet;
|
||||
try
|
||||
{
|
||||
_ActUtlType.ActLogicalStationNumber = Convert.ToInt32(localStationNum);
|
||||
//_DotUtlType.ActLogicalStationNumber = Convert.ToInt32(localStationNum);
|
||||
|
||||
lRet = _ActUtlType.Open();
|
||||
//lRet = _DotUtlType.Open();
|
||||
|
||||
if (lRet == 0)
|
||||
{
|
||||
m_IsPlcConnected = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite("Error Open PLC Connection.", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
m_IsPlcConnected = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite("Error during logical station opening: " + ex.Message, ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Close()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m_IsPlcConnected)
|
||||
{
|
||||
//_DotUtlType.Close();
|
||||
_ActUtlType.Close();
|
||||
}
|
||||
|
||||
m_IsPlcConnected = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite("Error during plc close: " + ex.Message, ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ReadData(string deviceName, int size, ref short[] data)
|
||||
{
|
||||
bool ret = false;
|
||||
int iRet = 0;
|
||||
|
||||
try
|
||||
{
|
||||
iRet = _ActUtlType.ReadDeviceRandom2(deviceName, size, out data[0]);
|
||||
//iRet = _DotUtlType.ReadDeviceRandom2(ref deviceName, size, ref data);
|
||||
|
||||
if (iRet == 0)
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
#if DEBUG
|
||||
MessageBox.Show(ex.ToString());
|
||||
#endif
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool BlockReadData(string deviceName, int size, ref short[] data)
|
||||
{
|
||||
bool ret = false;
|
||||
int iRet = 0;
|
||||
|
||||
try
|
||||
{
|
||||
iRet = _ActUtlType.ReadDeviceBlock2(deviceName, size, out data[0]);
|
||||
//iRet = _DotUtlType.ReadDeviceBlock2(ref deviceName, size, ref data);
|
||||
|
||||
if (iRet == 0)
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
#if DEBUG
|
||||
MessageBox.Show(ex.ToString());
|
||||
#endif
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
public bool WriteData(string deviceName, int size, short[] data)
|
||||
{
|
||||
bool ret = false;
|
||||
int iRet = 0;
|
||||
|
||||
try
|
||||
{
|
||||
iRet = _ActUtlType.WriteDeviceRandom2(deviceName, size, data[0]);
|
||||
//iRet = _DotUtlType.WriteDeviceRandom2(ref deviceName, size, ref data);
|
||||
|
||||
if (iRet == 0)
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
#if DEBUG
|
||||
MessageBox.Show(ex.ToString());
|
||||
#endif
|
||||
ret = false;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool BlockWriteData(string deviceName, int size, short[] data)
|
||||
{
|
||||
bool ret = false;
|
||||
int iRet = 0;
|
||||
|
||||
try
|
||||
{
|
||||
short[] blockValue = new short[size];
|
||||
Array.Copy(data, blockValue, data.Length);
|
||||
//Buffer.BlockCopy(data, 0, blockValue, 0, size);
|
||||
|
||||
iRet = _ActUtlType.WriteDeviceBlock2(deviceName, size, blockValue[0]);
|
||||
//iRet = _DotUtlType.WriteDeviceBlock2(ref deviceName, size, blockValue);
|
||||
|
||||
if (iRet == 0)
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
#if DEBUG
|
||||
MessageBox.Show(ex.ToString());
|
||||
#endif
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void ReleaseLock()
|
||||
{
|
||||
m_bLockFin = false;
|
||||
}
|
||||
|
||||
public bool GetLockState()
|
||||
{
|
||||
return m_bLockFin;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,250 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using SystemX.Net.Platform.Common.Util;
|
||||
|
||||
using static SystemX.PLC.Interface.PLCCommDefinition;
|
||||
using static SystemX.PLC.Model.ModelSetupTemplate;
|
||||
|
||||
namespace SystemX.PLC.Interface
|
||||
{
|
||||
public class PLCAddressManager
|
||||
{
|
||||
public bool AutoConnection { get; set; } = false;
|
||||
public Dictionary<string, ModelElementData> DescriptionDictionary { get; set; } = new Dictionary<string, ModelElementData>();
|
||||
public Dictionary<string, PLCAddressTemplate> DataDictionary { get; set; } = new Dictionary<string, PLCAddressTemplate>();
|
||||
public Dictionary<string, PLCAddressTemplate> OperationDictionary { get; set; } = new Dictionary<string, PLCAddressTemplate>();
|
||||
public Dictionary<string, PLCConnectionInfo> ConnInfoDictionary { get; set; } = new Dictionary<string, PLCConnectionInfo>();
|
||||
|
||||
public PLCAddressManager(string strPath)
|
||||
{
|
||||
LoadAddressXML(strPath);
|
||||
}
|
||||
|
||||
public ePLCAreaType AddressSectionCheck(string strName)
|
||||
{
|
||||
if (DataDictionary.Values.Where(x => x.DataName == strName).ToList().Count > 0)
|
||||
return ePLCAreaType.Data;
|
||||
else if (OperationDictionary.Values.Where(x => x.DataName == strName).ToList().Count > 0)
|
||||
return ePLCAreaType.Operation;
|
||||
else
|
||||
return ePLCAreaType.None;
|
||||
}
|
||||
|
||||
public bool IsDataSectionSignal(string strName)
|
||||
{
|
||||
if (DataDictionary.Values.Where(x => x.DataName == strName).ToList().Count > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsOperationSectionSignal(string strName)
|
||||
{
|
||||
if (OperationDictionary.Values.Where(x => x.DataName == strName).ToList().Count > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public PLCAddressTemplate FindDataDicPLCAddressElementByDataName(string strName)
|
||||
{
|
||||
List<PLCAddressTemplate> vtmplt = DataDictionary.Values.Where(x => x.DataName == strName).ToList();
|
||||
List<PLCAddressTemplate> vOpTmplt = OperationDictionary.Values.Where(x => x.DataName == strName).ToList();
|
||||
|
||||
vtmplt = vtmplt.Union(vOpTmplt).ToList();
|
||||
if (vtmplt.Count == 0)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"Cannot Find PLC Address which has a name as : {strName}.", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return vtmplt[0];
|
||||
}
|
||||
|
||||
public PLCAddressTemplate FindOperationPLCAddressElementByDataName(string strName)
|
||||
{
|
||||
List<PLCAddressTemplate> vtmplt = OperationDictionary.Values.Where(x => x.DataName == strName).ToList();
|
||||
|
||||
if (vtmplt.Count == 0)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"Cannot Find PLC Address which has a name as : {strName}.", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return vtmplt[0];
|
||||
}
|
||||
|
||||
public PLCAddressTemplate FindPLCOperationTemplateElementByPLCDevice(string PLCDevice)
|
||||
{
|
||||
List<PLCAddressTemplate> vTemplate = OperationDictionary.Values.Where(x => x.PLCAddress == PLCDevice).ToList();
|
||||
|
||||
if (vTemplate.Count <= 0)
|
||||
return null;
|
||||
|
||||
return vTemplate[0];
|
||||
}
|
||||
|
||||
public PLCAddressTemplate FindPLCAddressElement(string strKey)
|
||||
{
|
||||
PLCAddressTemplate tmplt = null;
|
||||
|
||||
if (DataDictionary.ContainsKey(strKey))
|
||||
tmplt = DataDictionary[strKey];
|
||||
else if (OperationDictionary.ContainsKey(strKey))
|
||||
tmplt = OperationDictionary[strKey];
|
||||
|
||||
return tmplt;
|
||||
}
|
||||
|
||||
public PLCAddressTemplate FindPLCAddressElementByDataName(string strDataName)
|
||||
{
|
||||
PLCAddressTemplate tmpltDataName = FindDataDicPLCAddressElementByDataName(strDataName);
|
||||
|
||||
if (tmpltDataName == null)
|
||||
tmpltDataName = FindOperationPLCAddressElementByDataName(strDataName);
|
||||
|
||||
return tmpltDataName;
|
||||
}
|
||||
|
||||
public PLCAddressTemplate FindPLCAddressElementByAssociatedKeyAddress(string strKeyAddress, Dictionary<string, PLCAddressTemplate> dicResult)
|
||||
{
|
||||
List<PLCAddressTemplate> vResults = (from addrTmplt in dicResult.Values where addrTmplt.IsMyAssociation(strKeyAddress) select addrTmplt).ToList();
|
||||
|
||||
if (vResults.Count > 0)
|
||||
return vResults[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void LoadAddressXML(string strXmlPath)
|
||||
{
|
||||
if (!File.Exists(strXmlPath))
|
||||
return;
|
||||
|
||||
XDocument xDoc = XDocument.Load(strXmlPath);
|
||||
|
||||
var xElement = xDoc.Element(PLCCommDefinition.ModelRoot);
|
||||
|
||||
if (xElement == null) return;
|
||||
|
||||
DescriptionDictionary = new Dictionary<string, ModelElementData>();
|
||||
DataDictionary = new Dictionary<string, PLCAddressTemplate>();
|
||||
OperationDictionary = new Dictionary<string, PLCAddressTemplate>();
|
||||
ConnInfoDictionary = new Dictionary<string, PLCConnectionInfo>();
|
||||
|
||||
var xelemDescRoot = xElement.Element(PLCCommDefinition.DescriptionRoot);
|
||||
var xelemConRoot = xElement.Element(PLCCommDefinition.ConnectionInfoRoot);
|
||||
var xelemOpRoot = xElement.Element(PLCCommDefinition.OpearationAreaRoot);
|
||||
var xelemDataRoot = xElement.Element(PLCCommDefinition.DataAreaRoot);
|
||||
|
||||
LoadXmlDataForDescTemplate(xelemDescRoot, DescriptionDictionary);
|
||||
LoadXmlDataForConninfoTemplate(xelemConRoot, ConnInfoDictionary);
|
||||
LoadXmlDataForDataTemplate(xelemOpRoot, OperationDictionary);
|
||||
LoadXmlDataForDataTemplate(xelemDataRoot, DataDictionary);
|
||||
|
||||
AutoConnection = Convert.ToBoolean(xelemConRoot.Attribute("AutoConnection").Value);
|
||||
}
|
||||
|
||||
void LoadXmlDataForDescTemplate(XElement xElemRoot, Dictionary<string, ModelElementData> dicResult)
|
||||
{
|
||||
foreach (XElement elem in xElemRoot.Elements())
|
||||
{
|
||||
if (elem.Name != PLCCommDefinition.DescElement)
|
||||
continue;
|
||||
|
||||
string strName = string.Empty;
|
||||
string strDataType = string.Empty;
|
||||
string strDesc = string.Empty;
|
||||
string strValue = elem.Value;
|
||||
|
||||
GetDescAttributes(elem, ref strName, ref strDataType, ref strDesc);
|
||||
dicResult.Add(strName, new ModelElementData() { Name = strName, DataType = strDataType, Desc = strDesc });
|
||||
}
|
||||
}
|
||||
|
||||
void GetDescAttributes(XElement xElem, ref string strName, ref string strType, ref string strDesc)
|
||||
{
|
||||
strName = string.Empty;
|
||||
strType = string.Empty;
|
||||
strDesc = string.Empty;
|
||||
|
||||
foreach (XAttribute xattrb in xElem.Attributes())
|
||||
{
|
||||
if (xattrb.Name == PLCCommDefinition.AttrbName)
|
||||
strName = xattrb.Value;
|
||||
else if (xattrb.Name == PLCCommDefinition.AttrbDataType)
|
||||
strType = xattrb.Value;
|
||||
else if (xattrb.Name == PLCCommDefinition.AttrbDesc)
|
||||
strDesc = xattrb.Value;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadXmlDataForConninfoTemplate(XElement xElemRoot, Dictionary<string, PLCConnectionInfo> dicResult)
|
||||
{
|
||||
foreach (XElement elem in xElemRoot.Elements())
|
||||
{
|
||||
if (elem.Name != PLCCommDefinition.ConnectionInfoElement)
|
||||
continue;
|
||||
|
||||
Dictionary<string, string> dicValue = new Dictionary<string, string>();
|
||||
|
||||
GetAddrAttributes(elem, dicValue);
|
||||
dicResult.Add(dicValue[PLCCommDefinition.eConnectionElem.Name.ToString()],
|
||||
new PLCConnectionInfo()
|
||||
{
|
||||
Name = dicValue[PLCCommDefinition.eConnectionElem.Name.ToString()],
|
||||
CPUType = dicValue[PLCCommDefinition.eConnectionElem.CPUType.ToString()],
|
||||
RWType = dicValue[PLCCommDefinition.eConnectionElem.RWType.ToString()],
|
||||
IP = dicValue[PLCCommDefinition.eConnectionElem.IP.ToString()],
|
||||
Port = dicValue[PLCCommDefinition.eConnectionElem.Port.ToString()],
|
||||
ConnectionType = dicValue[PLCCommDefinition.eConnectionElem.ConnectionType.ToString()],
|
||||
Timeout = dicValue[PLCCommDefinition.eConnectionElem.Timeout.ToString()]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void LoadXmlDataForDataTemplate(XElement xElemRoot, Dictionary<string, PLCAddressTemplate> dicResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (XElement elem in xElemRoot.Elements())
|
||||
{
|
||||
if (elem.Name != PLCCommDefinition.AddrElement)
|
||||
continue;
|
||||
|
||||
Dictionary<string, string> dicValue = new Dictionary<string, string>();
|
||||
|
||||
GetAddrAttributes(elem, dicValue);
|
||||
dicResult.Add(dicValue[PLCCommDefinition.AttrbAddrArea] + dicValue[PLCCommDefinition.AttrbAddrAddress],
|
||||
new PLCAddressTemplate()
|
||||
{
|
||||
Area = dicValue[PLCCommDefinition.AttrbAddrArea],
|
||||
Address = dicValue[PLCCommDefinition.AttrbAddrAddress],
|
||||
Length = dicValue[PLCCommDefinition.AttrbAddrLength],
|
||||
DataName = dicValue[PLCCommDefinition.AttrbAddrDataName],
|
||||
DataType = dicValue[PLCCommDefinition.AttrbAddrDataType],
|
||||
Operation = dicValue[PLCCommDefinition.AttrbAddrOperation],
|
||||
Desc = dicValue[PLCCommDefinition.AttrbAddrDesc]
|
||||
});
|
||||
|
||||
dicResult[dicValue[PLCCommDefinition.AttrbAddrArea] + dicValue[PLCCommDefinition.AttrbAddrAddress]].SetAssocationKeys();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"Error occured in LoadXmlDataForDataTemplate. \n - Error Message: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
void GetAddrAttributes(XElement xElem, Dictionary<string, string> dicValue)
|
||||
{
|
||||
foreach (XAttribute xattrb in xElem.Attributes())
|
||||
dicValue.Add(xattrb.Name.ToString(), xattrb.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SystemX.Net.Platform.Common.Util;
|
||||
using static SystemX.PLC.Interface.PLCCommDefinition;
|
||||
|
||||
namespace SystemX.PLC.Interface
|
||||
{
|
||||
public class PLCAddressTemplate
|
||||
{
|
||||
public string Area { get; set; } = string.Empty;
|
||||
public string Address { get; set; } = string.Empty;
|
||||
public string Length { get; set; } = string.Empty;
|
||||
public string DataName { get; set; } = string.Empty;
|
||||
public string DataType { get; set; } = string.Empty;
|
||||
public string Operation { get; set; } = string.Empty;
|
||||
public string Desc { get; set; } = string.Empty;
|
||||
public string AddressKey { get { return Area + Address; } }
|
||||
|
||||
List<string> AssociatedAddress { get; set; } = null;
|
||||
List<int> KeyAddressValues { get; set; } = null;
|
||||
|
||||
public string Value
|
||||
{
|
||||
get { return RefineInvalidChars(MakeResultValue()); }
|
||||
}
|
||||
|
||||
public List<int> RawValue
|
||||
{
|
||||
get { return KeyAddressValues; }
|
||||
}
|
||||
|
||||
public PLCAddressTemplate()
|
||||
{
|
||||
}
|
||||
|
||||
public void UpdateValue(string strKey, int nValue)
|
||||
{
|
||||
int nFindKeyAddrIdx = AssociatedAddress.IndexOf(strKey);
|
||||
|
||||
KeyAddressValues[nFindKeyAddrIdx] = nValue;
|
||||
}
|
||||
|
||||
public void SetStringValue(string strValue)
|
||||
{
|
||||
List<int> vnValues = new List<int>();
|
||||
int nLength = Convert.ToInt32(Length);
|
||||
eDataType eType = (eDataType)Enum.Parse(typeof(eDataType), DataType);
|
||||
|
||||
if (eType == eDataType.ASCII)
|
||||
vnValues = (from value in CommonUtil.HexStringToBytes(strValue) select Convert.ToInt32(value)).ToList();
|
||||
else if (eType == eDataType.DECIMAL)
|
||||
{
|
||||
int nInputValue = string.IsNullOrWhiteSpace(strValue) ? 0 : Convert.ToInt32(strValue);
|
||||
vnValues.Add(nInputValue);
|
||||
}
|
||||
|
||||
for (int i = 0; i < vnValues.Count; i++)
|
||||
KeyAddressValues[i] = vnValues[i];
|
||||
}
|
||||
|
||||
public void SetAssociatedValue(int nValue)
|
||||
{
|
||||
KeyAddressValues[0] = nValue;
|
||||
}
|
||||
|
||||
public void SetAssociatedValues(List<int> nValues)
|
||||
{
|
||||
for (int i = 0; i < nValues.Count; i++)
|
||||
KeyAddressValues[i] = nValues[i];
|
||||
}
|
||||
|
||||
public void SetAssocationKeys()
|
||||
{
|
||||
AssociatedAddress = new List<string>();
|
||||
KeyAddressValues = new List<int>();
|
||||
|
||||
int nLength = Convert.ToInt32(Length);
|
||||
int nStartAddress = Convert.ToInt32(Address);
|
||||
|
||||
for (int i = 0; i < nLength; i++)
|
||||
{
|
||||
AssociatedAddress.Add(Area + (nStartAddress + i).ToString());
|
||||
KeyAddressValues.Add(00);
|
||||
}
|
||||
}
|
||||
|
||||
public string PLCAddress { get { return Area + Address; } }
|
||||
|
||||
public bool IsMyAssociation(string strKey)
|
||||
{
|
||||
if (AssociatedAddress == null)
|
||||
SetAssocationKeys();
|
||||
|
||||
if (AssociatedAddress.Contains(strKey))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string MakeResultValue()
|
||||
{
|
||||
eDataType eType = (eDataType)Enum.Parse(typeof(eDataType), DataType);
|
||||
string strData = string.Empty;
|
||||
|
||||
if (eType == eDataType.ASCII)
|
||||
strData = CommonUtil.GetStringFromASCII(KeyAddressValues.ToArray());
|
||||
else if (eType == eDataType.BIT)
|
||||
strData = KeyAddressValues[0].ToString();
|
||||
else if (eType == eDataType.DECIMAL)
|
||||
strData = KeyAddressValues[0].ToString();
|
||||
|
||||
return strData;
|
||||
}
|
||||
|
||||
public string RefineInvalidChars(string strSource)
|
||||
{
|
||||
string strReturn = strSource.Trim(InvalidChars);
|
||||
|
||||
strReturn = new string((from cCode in strSource.ToCharArray() where (48 <= Convert.ToInt32(cCode) && Convert.ToInt32(cCode) <= 95) select cCode).ToArray());
|
||||
|
||||
return strReturn;
|
||||
}
|
||||
}
|
||||
|
||||
public class PLCConnectionInfo
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string CPUType { get; set; } = string.Empty;
|
||||
public string RWType { get; set; } = string.Empty;
|
||||
public string IP { get; set; } = string.Empty;
|
||||
public string Port { get; set; } = string.Empty;
|
||||
public string ConnectionType { get; set; } = string.Empty;
|
||||
public string Timeout { get; set; } = string.Empty;
|
||||
|
||||
public PLCConnectionInfo()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemX.PLC.Interface
|
||||
{
|
||||
public static class PLCCommDefinition
|
||||
{
|
||||
public delegate void EventPLCHandler(string address, int value);
|
||||
|
||||
public static string ModelRoot = "PLCAddress";
|
||||
|
||||
public static string DescriptionRoot = "Description";
|
||||
public static string OpearationAreaRoot = "OpearationArea";
|
||||
public static string DataAreaRoot = "DataArea";
|
||||
public static string ConnectionInfoRoot = "ConnectionInfo";
|
||||
|
||||
public static char[] InvalidChars = new [] { '\\', '\n', '\r', '@', '#', '$', '%', '^', '&',
|
||||
'*', '!', '(', ')', '┌', ''};
|
||||
|
||||
#region Description Attributes
|
||||
public static string DescElement = "Element";
|
||||
public static string AttrbName = "Name";
|
||||
public static string AttrbDataType = "DataType";
|
||||
public static string AttrbDesc = "Desc";
|
||||
#endregion
|
||||
|
||||
#region ConnectionInfo Attributes
|
||||
public static string ConnectionInfoElement = "ConnectionDef";
|
||||
public enum eConnectionElem
|
||||
{
|
||||
Name ,
|
||||
CPUType ,
|
||||
RWType,
|
||||
IP ,
|
||||
Port ,
|
||||
ConnectionType,
|
||||
Timeout
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PLC Address Attributes
|
||||
public static string AddrElement = "AddressElement";
|
||||
public static string AttrbAddrArea = "Area";
|
||||
public static string AttrbAddrAddress = "Address";
|
||||
public static string AttrbAddrLength = "Length";
|
||||
public static string AttrbAddrDataName = "DataName";
|
||||
public static string AttrbAddrDataType = "DataType";
|
||||
public static string AttrbAddrOperation = "Operation";
|
||||
public static string AttrbAddrDesc = "Desc";
|
||||
#endregion
|
||||
|
||||
public enum ePLCRWType
|
||||
{
|
||||
Read,
|
||||
Write,
|
||||
ReadWrite
|
||||
}
|
||||
|
||||
public enum eDataType
|
||||
{
|
||||
ASCII,
|
||||
DECIMAL,
|
||||
BIT
|
||||
}
|
||||
|
||||
public enum ePLCAreaType
|
||||
{
|
||||
None,
|
||||
Operation,
|
||||
Data
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SystemX.Net.Platform.Common.Event;
|
||||
using SystemX.Net.Platform.Common.Util;
|
||||
using SystemX.PLC.Interface;
|
||||
using static SystemX.PLC.Interface.PLCCommDefinition;
|
||||
|
||||
namespace SystemX.PLC.Interface
|
||||
{
|
||||
public class PLCCommManager
|
||||
{
|
||||
public PLCAddressManager AddrMgr { get; set; }
|
||||
public FunctionEventHandler EventChangeUpdate { get; set; }
|
||||
public bool OperationStarted { get; set; } = false;
|
||||
|
||||
public PLCCommManager(string strPLCConnInfoXmlPath)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool OpenPLCConnection()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool StartPLCOperation()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public virtual void NowScanDataArea()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual bool StopPLCOperation()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public virtual bool ClosePLCConnection()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void ReceivePLCEvent(string address, int value)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual string GetDeviceValue(PLCAddressTemplate tmplt)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
public virtual string ReadDevice(string strDevice, bool bRefineWrongChar = true)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
public virtual string ReadDevice(PLCAddressTemplate tmplt)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
public virtual string ReadDevice(PLCAddressTemplate tmplt, bool bAsciiReverse = false)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
public virtual void UpdateAll(bool bRefineWrongChar)
|
||||
{
|
||||
}
|
||||
public virtual void SelectUpdate(ePLCAreaType pat, PLCAddressTemplate tmplt, bool bRefineWrongChar)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool WriteDevice(PLCAddressTemplate tmplt, string strValue, bool bVerification = false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
129
SystemX.Net.CP.Platform/SystemX.PLC/Interface/PLCDevice.cs
Normal file
129
SystemX.Net.CP.Platform/SystemX.PLC/Interface/PLCDevice.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Dsu.PLC.Melsec;
|
||||
using Dsu.PLC;
|
||||
using Dsu.PLC.Common;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using SystemX.Net.Platform.Common.Event;
|
||||
using SystemX.Net.Platform.Common.Util;
|
||||
using System.Reactive.Linq;
|
||||
|
||||
namespace SystemX.PLC.Interface
|
||||
{
|
||||
public class PLCDevice
|
||||
{
|
||||
public FunctionEventHandler FuncEvtHndl { get; set; }
|
||||
public string CPU_TYPE_STR { set; get; } //Example: "Q03UDECPU";
|
||||
public string PLC_IP_ADDR { set; get; }
|
||||
public int PLC_PORT_NUMBER { set; get; }
|
||||
public string CONNECTION_TYPE_STR { set; get; }
|
||||
public int TIMEOUT { set; get; }
|
||||
public bool READPORT { set; get; }
|
||||
public string DeviceID { set; get; }
|
||||
|
||||
private MxConnection _conn; // Read port UDP Write port TCP
|
||||
|
||||
public bool DevClose()
|
||||
{
|
||||
return _conn.Disconnect();
|
||||
}
|
||||
|
||||
public bool DevOpen()
|
||||
{
|
||||
try
|
||||
{
|
||||
TransportProtocol ConType = CONNECTION_TYPE_STR.ToUpper() == "TCP" ? TransportProtocol.Tcp : TransportProtocol.Udp;
|
||||
_conn = new MxConnection(new MxConnectionParameters(PLC_IP_ADDR, Convert.ToUInt16(PLC_PORT_NUMBER), ConType));
|
||||
return _conn.Connect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite(ex.Message, ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AddDevices(string deviceNames)
|
||||
{
|
||||
_conn.CreateTag(deviceNames);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task SingleScanStartAsync()
|
||||
{
|
||||
if (_conn.Tags.Count == 0)
|
||||
return;
|
||||
|
||||
int readCount = 0;
|
||||
_conn.PerRequestDelay = TIMEOUT;
|
||||
_conn.Subject.OfType<TagValueChangedEvent>().Subscribe(evt =>
|
||||
{
|
||||
readCount++;
|
||||
EventTag((MxTag)evt.Tag);
|
||||
});
|
||||
_conn.StartDataExchangeLoopAsync(); // Do not use await
|
||||
// _conn.Disconnect();
|
||||
|
||||
Stopwatch xSW = new Stopwatch();
|
||||
xSW.Start();
|
||||
bool bSuccess = true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (_conn.Tags.Count <= readCount)
|
||||
break;
|
||||
else
|
||||
System.Threading.Thread.Sleep(50);
|
||||
|
||||
if (xSW.ElapsedMilliseconds > 5000)
|
||||
{
|
||||
bSuccess = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bSuccess)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite("Trouble in Single Scan Start Async", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
//await SingleScanStartAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private void EventTag(MxTag tag)
|
||||
{
|
||||
if (tag.IsBitDevice)
|
||||
FuncEvtHndl.DoReceive(this, tag.Name + ";" + (Convert.ToBoolean(tag.Value) ? 1 : 0).ToString());
|
||||
else
|
||||
FuncEvtHndl.DoReceive(this, tag.Name + ";" + tag.Value.ToString());
|
||||
}
|
||||
|
||||
|
||||
public bool WriteBitDevice(string strDeviceWrite, int[] value)
|
||||
{
|
||||
//Console.WriteLine(string.Format("{0} : {1}", strDeviceWrite, value[0]));
|
||||
return _conn.McProtocol.SetBitDevice(strDeviceWrite, 1, value) == 0;
|
||||
}
|
||||
|
||||
public bool WriteDevice(string strDeviceWrite, int value)
|
||||
{
|
||||
//Console.WriteLine(string.Format("{0} : {1}", strDeviceWrite, value));
|
||||
return _conn.McProtocol.SetDevice(strDeviceWrite, Convert.ToInt32(value)) == 0;
|
||||
}
|
||||
|
||||
public int ReadDevice(string strDeviceRead)
|
||||
{
|
||||
int value;
|
||||
_conn.McProtocol.GetDevice(strDeviceRead, out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public string GetModuleName()
|
||||
{
|
||||
return Assembly.GetExecutingAssembly().ManifestModule.Name.Replace(".dll", string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
171
SystemX.Net.CP.Platform/SystemX.PLC/Interface/PLCModMgr.cs
Normal file
171
SystemX.Net.CP.Platform/SystemX.PLC/Interface/PLCModMgr.cs
Normal file
@ -0,0 +1,171 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Threading;
|
||||
using SystemX.Net.Platform.Common.Event;
|
||||
using SystemX.Net.Platform.Common.Util;
|
||||
using static SystemX.PLC.Interface.PLCCommDefinition;
|
||||
|
||||
namespace SystemX.PLC.Interface
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Example to represent how to build a device manager.
|
||||
/// A Device Manager constructs a device in run-time environment using a defined dll name in the configuration xml.
|
||||
/// The named dll for a device is bound in run-time environment as well.
|
||||
/// Device manager is an inherited class from a CpDeviceManagerBase and a corresponding interface.
|
||||
/// </summary>
|
||||
public class PLCModMgr
|
||||
{
|
||||
public event EventPLCHandler EventPLC;
|
||||
public FunctionEventHandler FuncEvtHndl;
|
||||
public PLCDevice plcDev;
|
||||
public PLCConnectionInfo PLCInfo;
|
||||
|
||||
public bool IsOpened { get; set; } = false;
|
||||
|
||||
public PLCModMgr(PLCConnectionInfo infoinput)
|
||||
{
|
||||
PLCInfo = infoinput;
|
||||
}
|
||||
|
||||
public bool CloseDevice()
|
||||
{
|
||||
bool bResult = plcDev.DevClose();
|
||||
|
||||
IsOpened = !bResult;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OpenDevice()
|
||||
{
|
||||
if (IsOpened == true)
|
||||
return IsOpened;
|
||||
|
||||
plcDev = new PLCDevice();
|
||||
FuncEvtHndl = new FunctionEventHandler();
|
||||
//FuncEvtHndl.OnReceive += FuncEvtHndl_OnPLCReceive;
|
||||
|
||||
plcDev.FuncEvtHndl = FuncEvtHndl;
|
||||
plcDev.DeviceID = PLCInfo.Name;
|
||||
plcDev.CPU_TYPE_STR = PLCInfo.CPUType;
|
||||
plcDev.PLC_IP_ADDR = PLCInfo.IP;
|
||||
plcDev.PLC_PORT_NUMBER = Convert.ToInt32(PLCInfo.Port);
|
||||
plcDev.CONNECTION_TYPE_STR = PLCInfo.ConnectionType != "UDP" ? "TCP" : "UDP";
|
||||
plcDev.READPORT = (PLCInfo.RWType == PLCCommDefinition.ePLCRWType.Read.ToString()) ? true : false;
|
||||
plcDev.TIMEOUT = Convert.ToInt32(PLCInfo.Timeout);
|
||||
|
||||
Task<bool> conPing = new Task<bool>(() => PingToPLC());
|
||||
|
||||
conPing.Start();
|
||||
|
||||
Task<bool> conPLC = conPing.ContinueWith(x => ConnectToPLC());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool PingToPLC()
|
||||
{
|
||||
try
|
||||
{
|
||||
Ping pingtoPLC = new Ping();
|
||||
int nCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
PingReply reply = pingtoPLC.Send(PLCInfo.IP);
|
||||
|
||||
if (reply.Status == IPStatus.Success)
|
||||
break;
|
||||
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Connection Failed. Retry #{nCount} - IP:{PLCInfo.IP}, Port:{PLCInfo.Port}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
|
||||
|
||||
Thread.Sleep(1000);
|
||||
nCount++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - PLC Connection error: {PLCInfo.Name}, {PLCInfo.IP}:{PLCInfo.Port} - {PLCInfo.ConnectionType}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" -> Reason: {ex.Message}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ConnectToPLC()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
IsOpened = plcDev.DevOpen();
|
||||
|
||||
if (IsOpened == false)
|
||||
plcDev = null;
|
||||
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Connection Success. - IP:{PLCInfo.IP}, Port:{PLCInfo.Port} ", ConsoleColor.Green, LogMessage.LogMessageLevel.NONE);
|
||||
|
||||
return IsOpened;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - PLC Connection error: {PLCInfo.Name}, {PLCInfo.IP}:{PLCInfo.Port} - {PLCInfo.ConnectionType}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" -> Reason: {ex.Message}", ConsoleColor.Blue, LogMessage.LogMessageLevel.NONE);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void FuncEvtHndl_OnPLCReceive(object sender, string data)
|
||||
{
|
||||
if (data.Contains(";"))
|
||||
{
|
||||
string address = data.Split(';')[0];
|
||||
int value = Convert.ToInt32(data.Split(';')[1]);
|
||||
|
||||
EventPLC?.Invoke(address, value);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SingleScanStartAsync()
|
||||
{
|
||||
if (!IsOpened) return;
|
||||
await plcDev.SingleScanStartAsync();
|
||||
}
|
||||
|
||||
public bool AddDevices(string deviceNames)
|
||||
{
|
||||
if (!IsOpened) return false;
|
||||
|
||||
return plcDev.AddDevices(deviceNames);
|
||||
}
|
||||
|
||||
public int ReadDevice(string deviceName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsOpened) return -1;
|
||||
return plcDev.ReadDevice(deviceName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage.MessageOutput.ConsoleWrite($"PLC Device Reading Error: {deviceName}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
LogMessage.MessageOutput.ConsoleWrite($" - Detail: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.NONE);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public bool WriteDevice(string deviceName, int value)
|
||||
{
|
||||
if (!IsOpened) return false;
|
||||
return plcDev.WriteDevice(deviceName, value);
|
||||
}
|
||||
|
||||
public bool WriteBitDevice(string deviceName, int[] value)
|
||||
{
|
||||
if (!IsOpened) return false;
|
||||
return plcDev.WriteBitDevice(deviceName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user