Files
CPXV2/SystemX.Net.CP.Platform/SystemX.PLC/Interface/MxComponent/PLCDeviceMXC.cs
2024-06-26 10:30:00 +09:00

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