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