[성현모] 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,18 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.3.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -0,0 +1,39 @@
namespace SystemX.PLC
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Text = "Form1";
}
#endregion
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SystemX.PLC
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}

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

View File

@ -0,0 +1,210 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using SystemX.Net.Platform.Common.Util;
using static SystemX.PLC.Model.ModelSetupTemplate;
namespace SystemX.PLC.Model
{
public class ModelCtrl
{
public Dictionary<string, ModelSetupTemplate> ModelDataResult { get; set; } = null;
public ModelSetupTemplate ModelTmpStd { get; set; }
public DataTable TemplateTable { get; set; } = null;
public DataTable ModelTable { get; set; } = null;
public string ModelPath { get; set; }
public ModelCtrl(string strModelTmpPath, string strModelPath)
{
ModelTmpStd = new ModelSetupTemplate(strModelTmpPath);
TemplateTable = CreateDescDataTable(ModelTmpStd);
ModelTable = OpenModelData(strModelPath);
ModelPath = strModelPath;
}
#region Initialization
DataTable OpenModelData(string strModelPath)
{
DataTable dtSetup = new DataTable();
List<string> vReadData = null;
CreateDTTemplate(dtSetup, ModelTmpStd);
if (File.Exists(strModelPath))
vReadData = OpenModelFile(strModelPath);
ModelDataResult = ReadModelData(vReadData, ModelTmpStd);
CreateModelDatatable(dtSetup, ModelDataResult);
return dtSetup;
}
DataTable CreateDescDataTable(ModelSetupTemplate model_tmpstd)
{
DataTable dtSetup = new DataTable();
dtSetup.Columns.Add(ModelTemplateDefinition.DescTableName);
dtSetup.Columns.Add(ModelTemplateDefinition.DescTableValue);
foreach (string strKey in model_tmpstd.ModelDescriptionDictionary.Keys)
{
DataRow dtRow = dtSetup.NewRow();
dtRow[ModelTemplateDefinition.DescTableName] = model_tmpstd.ModelDescriptionDictionary[strKey].Name;
dtRow[ModelTemplateDefinition.DescTableValue] = model_tmpstd.ModelDescriptionDictionary[strKey].Desc;
dtSetup.Rows.Add(dtRow);
}
return dtSetup;
}
void CreateDTTemplate(DataTable dtResult, ModelSetupTemplate model_tmpstd)
{
foreach (string strKey in model_tmpstd.ModelDataDictionary.Keys)
{
DataRow dtRow = dtResult.NewRow();
Type typeTarget = CommonUtil.GetType(model_tmpstd.ModelDataDictionary[strKey].DataType);
if (typeTarget == null) return;
dtResult.Columns.Add(model_tmpstd.ModelDataDictionary[strKey].Name, typeTarget, model_tmpstd.ModelDataDictionary[strKey].Desc);
if (model_tmpstd.ModelDataDictionary[strKey].IsIDKey)
dtResult.Columns[model_tmpstd.ModelDataDictionary[strKey].Name].Unique = true;
}
}
void CreateModelDatatable(DataTable dtResult, Dictionary<string, ModelSetupTemplate> vModelData)
{
try
{
if (vModelData == null)
return;
foreach (ModelSetupTemplate vModel in vModelData.Values)
{
DataRow dtRow = dtResult.NewRow();
foreach (string strKey in vModel.ModelDataDictionary.Keys)
{
ModelElementData elemData = vModel.ModelDataDictionary[strKey];
object objValue = elemData.RValue;
if (objValue == null)
continue;
dtRow[strKey] = objValue;
}
dtResult.Rows.Add(dtRow);
}
}
catch (Exception ex)
{
LogMessage.MessageOutput.ConsoleWrite($"Error in CreateModelDatatable. Error Message: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
}
}
public void UpdateModelDataTable()
{
ModelTable.Clear();
CreateModelDatatable(ModelTable, ModelDataResult);
}
Dictionary<string, ModelSetupTemplate> ReadModelData(List<string> vstrModel, ModelSetupTemplate model_tmpstd)
{
if (vstrModel == null || vstrModel.Count <= 0)
return null;
Dictionary<string, ModelSetupTemplate> dicResultModel = new Dictionary<string, ModelSetupTemplate>();
List<string> vstrColumn = vstrModel[0].Split(ModelTemplateDefinition.ModelFileDelimiter.ToCharArray()).Where(x => x != string.Empty).ToList();
vstrModel.RemoveAt(0);
try
{
foreach (string strModel in vstrModel)
{
List<string> vstrModelLine = strModel.Split(ModelTemplateDefinition.ModelFileDelimiter.ToCharArray()).ToList();
ModelSetupTemplate modelstr = model_tmpstd.GetNewModelStructure();
if (!CreateModelData(vstrColumn, vstrModelLine, modelstr))
continue;
dicResultModel.Add(modelstr.GetPrimaryKey().Value, modelstr);
}
}
catch (Exception ex)
{
LogMessage.MessageOutput.ConsoleWrite($"Error occured in ModelCtrl.ReadModelData. Error Message: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
}
return dicResultModel;
}
bool CreateModelData(List<string> vstrColumn, List<string> vstrModelLine, ModelSetupTemplate modelstr)
{
string strColumnName = string.Empty;
try
{
for (int i = 0; i < vstrColumn.Count; i++)
{
strColumnName = vstrColumn[i];
modelstr.ModelDataDictionary[strColumnName].Value = vstrModelLine[i];
}
return true;
}
catch (Exception ex)
{
LogMessage.MessageOutput.ConsoleWrite("Error to find a column or a value. Column Name: " + strColumnName + "\n - Error Message: " + ex.Message, ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
return false;
}
}
List<string> OpenModelFile(string strPath)
{
List<string> vstrData = new List<string>();
//IntPtr safeADSHandle = NativeMethods.CreateFile(strPath, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);
FileStream fs = new FileStream(strPath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
while (!sr.EndOfStream)
vstrData.Add(sr.ReadLine());
sr.Close();
fs.Close();
return vstrData;
}
#endregion
public ModelSetupTemplate FindElement(string strKey)
{
return ModelDataResult[strKey];
}
public void SaveModel(string strPath)
{
string strSavePath = string.IsNullOrEmpty(strPath) ? ModelPath : strPath;
//IntPtr safeADSHandle = NativeMethods.CreateFile(strSavePath, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);
FileStream fs = new FileStream(strSavePath, FileMode.Truncate, FileAccess.ReadWrite);
StreamWriter sr = new StreamWriter(fs);
sr.WriteLine(ModelTmpStd.GetSaveModelColName());
foreach (ModelSetupTemplate model in ModelDataResult.Values)
{
string strLine = model.GetSaveModelValue();
sr.WriteLine(strLine);
}
sr.Close();
fs.Close();
}
}
}

View File

@ -0,0 +1,218 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using SystemX.Net.Platform.Common.Util;
namespace SystemX.PLC.Model
{
public class ModelSetupTemplate
{
public class ModelElementData
{
public ModelElementData() { }
public ModelElementData(ModelElementData model)
{
Name = model.Name;
DataType = model.DataType;
Desc = model.Desc;
Value = model.Value;
IsIDKey = model.IsIDKey;
ChangeType();
}
string InternalValue { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string DataType { get; set; } = string.Empty;
public string Desc { get; set; } = string.Empty;
public string Value
{
get { return InternalValue; }
set
{
string strChangineValue = value;
Type tResult = CommonUtil.GetType(DataType);
if (tResult == typeof(System.Boolean) && !string.IsNullOrWhiteSpace(Value))
{
int nValue = strChangineValue == true.ToString() ? 1 : 0;
InternalValue = nValue.ToString();
}
else
InternalValue = strChangineValue;
}
}
public object RValue { get { ChangeType(); return objConvertedValue; } }
object objConvertedValue = null;
public bool IsIDKey { get; set; } = false;
void ChangeType()
{
try
{
Type tResult = CommonUtil.GetType(DataType);
string strChangineValue = Value;
if (string.IsNullOrEmpty(strChangineValue) && tResult != typeof(System.Boolean))
return;
if (tResult == typeof(System.Boolean))
{
if (!string.IsNullOrWhiteSpace(Value))
{
bool bValue = false;
int nValue = 0;
if (Boolean.TryParse(Value, out bValue))
strChangineValue = bValue.ToString();
else if (Int32.TryParse(Value, out nValue))
strChangineValue = nValue == 0 ? false.ToString() : true.ToString();
}
else
strChangineValue = false.ToString();
}
objConvertedValue = Convert.ChangeType(strChangineValue, tResult);
}
catch (Exception ex)
{
LogMessage.MessageOutput.ConsoleWrite($"Converting Error on <{Name}>, Value: {Value}. \n - Error Message: {ex.Message}", ConsoleColor.Red, LogMessage.LogMessageLevel.FATAL);
}
}
}
public Dictionary<string, ModelElementData> ModelDescriptionDictionary { get; set; }
public Dictionary<string, ModelElementData> ModelDataDictionary { get; set; }
public ModelSetupTemplate(ModelSetupTemplate model)
{
ModelDescriptionDictionary = CloneDictionary(model.ModelDescriptionDictionary);
ModelDataDictionary = CloneDictionary(model.ModelDataDictionary);
}
public ModelSetupTemplate(string strTemplatePath)
{
ModelDescriptionDictionary = new Dictionary<string, ModelElementData>();
ModelDataDictionary = new Dictionary<string, ModelElementData>();
LoadXmlConfig(strTemplatePath);
}
public ModelElementData GetPrimaryKey()
{
List<ModelElementData> vModelelemdata = ModelDataDictionary.Values.Where(x => x.IsIDKey == true).ToList();
return vModelelemdata.Count > 0 ? vModelelemdata[0] : null;
}
public ModelElementData FindKey(string strName)
{
return ModelDataDictionary[strName];
}
public string GetSaveModelColName()
{
string strResult = string.Empty;
foreach (ModelElementData element in ModelDataDictionary.Values)
strResult += element.Name + ModelTemplateDefinition.ModelFileDelimiter;
strResult = strResult.Remove((strResult.Length - 1), 1);
return strResult;
}
public string GetSaveModelValue()
{
string strResult = string.Empty;
foreach (ModelElementData element in ModelDataDictionary.Values)
strResult += element.Value + ModelTemplateDefinition.ModelFileDelimiter;
strResult = strResult.Remove((strResult.Length - 1), 1);
return strResult;
}
#region Initialization
void LoadXmlConfig(string strXmlPath)
{
if (!File.Exists(strXmlPath))
return;
XDocument xDoc = XDocument.Load(strXmlPath);
var xElement = xDoc.Element(ModelTemplateDefinition.ModelRoot);
if (xElement == null) return;
var xelemDescRoot = xElement.Element(ModelTemplateDefinition.DescriptionRoot);
var xelemDSRoot = xElement.Element(ModelTemplateDefinition.DSRoot);
LoadXmlDataForTemplate(xelemDescRoot, ModelDescriptionDictionary);
LoadXmlDataForTemplate(xelemDSRoot, ModelDataDictionary);
}
public void LoadXmlDataForTemplate(XElement xElemRoot, Dictionary<string, ModelElementData> dicResult)
{
foreach (XElement elem in xElemRoot.Elements())
{
if (elem.Name != ModelTemplateDefinition.Element)
continue;
string strName = string.Empty;
string strDataType = string.Empty;
string strDesc = string.Empty;
string strValue = elem.Value;
bool bIDKey = strValue == ModelTemplateDefinition.IDKeyMark ? true : false;
GetAttributes(elem, ref strName, ref strDataType, ref strDesc);
dicResult.Add(strName, new ModelElementData() { Name = strName, DataType = strDataType, Desc = strDesc, IsIDKey = bIDKey });
}
if (GetPrimaryKey() == null)
dicResult[dicResult.Keys.ElementAt(0)].IsIDKey = true;
}
void GetAttributes(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 == ModelTemplateDefinition.AttrbName)
strName = xattrb.Value;
else if (xattrb.Name == ModelTemplateDefinition.AttrbDataType)
strType = xattrb.Value;
else if (xattrb.Name == ModelTemplateDefinition.AttrbDesc)
strDesc = xattrb.Value;
}
}
public ModelSetupTemplate GetNewModelStructure()
{
ModelSetupTemplate model = new ModelSetupTemplate(this);
return model;
}
Dictionary<string, ModelElementData> CloneDictionary(Dictionary<string, ModelElementData> dicOrg)
{
Dictionary<string, ModelElementData> dicClone = new Dictionary<string, ModelElementData>();
foreach (string strKey in dicOrg.Keys)
{
ModelElementData modeldata = new ModelElementData(dicOrg[strKey]);
dicClone.Add(strKey, modeldata);
}
return dicClone;
}
#endregion
}
}

View File

@ -0,0 +1,21 @@
namespace SystemX.PLC.Model
{
public static class ModelTemplateDefinition
{
public static string ModelRoot = "ModelTemplate";
public static string DescriptionRoot = "Description";
public static string DSRoot = "DataStructure";
public static string Element = "Element";
public static string AttrbName = "Name";
public static string AttrbDataType = "DataType";
public static string AttrbDesc = "Desc";
public static string DescTableName = "Name";
public static string DescTableValue = "Description";
public static string IDKeyMark = "IDKey";
public static string ModelFileDelimiter = ";";
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SystemX.PLC.Interface;
using SystemX.PLC.Interface.McProtocol;
using SystemX.PLC.Interface.MxComponent;
namespace SystemX.PLC
{
public enum ConnectionType
{
Mitsubishi_McProtocol = 0,
Mitsubishi_MxComponent
}
public static class PLCInstanciation
{
public static PLCCommManager CreatePLCCommManager(ConnectionType type, string strConfigFilePath)
{
switch(type)
{
case ConnectionType.Mitsubishi_McProtocol:
return new PLCCommMcPMgr(strConfigFilePath);
case ConnectionType.Mitsubishi_MxComponent:
return new PLCCommMxCMgr(strConfigFilePath);
default:
return null;
}
}
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SystemX.PLC
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SystemX.PLC")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SystemX.PLC")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("56642dc5-c7ef-4040-acfc-fec17ec717d6")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SystemX.PLC.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SystemX.PLC.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SystemX.PLC.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{56642DC5-C7EF-4040-ACFC-FEC17EC717D6}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SystemX.PLC</RootNamespace>
<AssemblyName>SystemX.PLC</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\Output.SystemX\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\Output.SystemX\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="Dsu.Common.Utilities.Core">
<HintPath>..\ExtLib\McProtocol\Dsu.Common.Utilities.Core.dll</HintPath>
</Reference>
<Reference Include="Dsu.Common.Utilities.FS">
<HintPath>..\ExtLib\McProtocol\Dsu.Common.Utilities.FS.dll</HintPath>
</Reference>
<Reference Include="Dsu.Driver.Base.FS">
<HintPath>..\ExtLib\McProtocol\Dsu.Driver.Base.FS.dll</HintPath>
</Reference>
<Reference Include="Dsu.Driver.Util">
<HintPath>..\ExtLib\McProtocol\Dsu.Driver.Util.dll</HintPath>
</Reference>
<Reference Include="Dsu.PLC.Melsec">
<HintPath>..\ExtLib\McProtocol\Dsu.PLC.Melsec.dll</HintPath>
</Reference>
<Reference Include="FSharp.Core">
<HintPath>..\ExtLib\McProtocol\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Reactive.Core">
<HintPath>..\ExtLib\System.Reactive.Core.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Interfaces">
<HintPath>..\ExtLib\System.Reactive.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Linq">
<HintPath>..\ExtLib\System.Reactive.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Interface\PLCAddressManager.cs" />
<Compile Include="Interface\PLCAddressTemplate.cs" />
<Compile Include="Interface\PLCCommDefinition.cs" />
<Compile Include="Interface\McProtocol\PLCCommMcPMgr.cs" />
<Compile Include="Interface\PLCCommManager.cs" />
<Compile Include="Interface\PLCDevice.cs" />
<Compile Include="Interface\McProtocol\PLCDeviceMXC.cs" />
<Compile Include="Interface\PLCModMgr.cs" />
<Compile Include="Interface\McProtocol\PLCModMxCMgr.cs" />
<Compile Include="Interface\MxComponent\PLCCommMxCMgr.cs" />
<Compile Include="Interface\MxComponent\PLCDeviceMXC.cs" />
<Compile Include="Interface\MxComponent\PLCModMxCMgr.cs" />
<Compile Include="Interface\MxComponent\PLCMxComponent.cs" />
<Compile Include="Model\ModelCtrl.cs" />
<Compile Include="Model\ModelSetupTemplate.cs" />
<Compile Include="Model\ModelTemplateDefinition.cs" />
<Compile Include="PLCInstanciation.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SystemX.Net.Platform\SystemX.Net.CP.Platform.csproj">
<Project>{9e024203-a0d4-4a08-8041-9d31248b6f7b}</Project>
<Name>SystemX.Net.CP.Platform</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<COMReference Include="ACTETHERLib">
<Guid>{A306B168-AE98-11D3-83AE-00A024BDBF2B}</Guid>
<VersionMajor>3</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
<COMReference Include="ActUtlTypeLib">
<Guid>{D217E54E-4A26-4A76-B0AB-57166B90F9AF}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>