315 lines
9.0 KiB
C#
315 lines
9.0 KiB
C#
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());
|
|
}
|
|
}
|
|
}
|