[성현모] CPXV2 Init

This commit is contained in:
SHM
2024-06-26 10:30:00 +09:00
parent cdf12248c5
commit 5958993b6a
588 changed files with 698420 additions and 0 deletions

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -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());
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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()
{
}
}
}

View File

@ -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
}
}
}

View File

@ -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;
}
}
}

View 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);
}
}
}

View 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);
}
}
}