2026-06-05 09:59:19 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using Aitex.Core.RT.IOCore;
|
2026-03-24 15:04:02 +08:00
|
|
|
|
using MECF.Framework.Common.IOCore;
|
|
|
|
|
|
using MECF.Framework.Common.PLC;
|
|
|
|
|
|
|
|
|
|
|
|
namespace SicSimulator.Instances
|
|
|
|
|
|
{
|
|
|
|
|
|
public class SimulatorAdsPlcService : IWcfPlcService
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
//diVariable="" doVariable="" aiVariable="" aoVariable=""
|
|
|
|
|
|
public bool CheckIsConnected()
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool Read(string variable, out object data, string type, int length, out string reason)
|
|
|
|
|
|
{
|
|
|
|
|
|
reason = string.Empty;
|
|
|
|
|
|
data = null;
|
|
|
|
|
|
|
2026-06-05 09:59:19 +08:00
|
|
|
|
if (!TryParseIoVariable(variable, out var pmSource, out var ioType, out var bufferIndex))
|
|
|
|
|
|
return true;
|
2026-03-24 15:04:02 +08:00
|
|
|
|
|
2026-06-05 09:59:19 +08:00
|
|
|
|
switch (ioType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case "DI":
|
|
|
|
|
|
data = IoManager.Instance.GetDiBuffer(pmSource)[bufferIndex];
|
2026-05-21 15:23:06 +08:00
|
|
|
|
break;
|
2026-06-05 09:59:19 +08:00
|
|
|
|
case "DO":
|
|
|
|
|
|
data = IoManager.Instance.GetDoBuffer(pmSource)[bufferIndex];
|
2026-03-24 15:04:02 +08:00
|
|
|
|
break;
|
2026-06-05 09:59:19 +08:00
|
|
|
|
case "AI":
|
|
|
|
|
|
data = IoManager.Instance.GetAiBuffer(pmSource)[bufferIndex];
|
2026-03-24 15:04:02 +08:00
|
|
|
|
break;
|
2026-06-05 09:59:19 +08:00
|
|
|
|
case "AO":
|
|
|
|
|
|
data = IoManager.Instance.GetAoBuffer(pmSource)[bufferIndex];
|
2026-05-21 15:23:06 +08:00
|
|
|
|
break;
|
2026-03-24 15:04:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool WriteArrayElement(string variable, int index, object value, out string reason)
|
|
|
|
|
|
{
|
|
|
|
|
|
reason = string.Empty;
|
|
|
|
|
|
|
2026-06-05 09:59:19 +08:00
|
|
|
|
if (!TryParseIoVariable(variable, out var pmSource, out var ioType, out var bufferIndex))
|
|
|
|
|
|
return true;
|
2026-05-21 15:23:06 +08:00
|
|
|
|
|
2026-06-05 09:59:19 +08:00
|
|
|
|
switch (ioType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case "DI":
|
2026-05-21 15:23:06 +08:00
|
|
|
|
break;
|
2026-06-05 09:59:19 +08:00
|
|
|
|
case "DO":
|
|
|
|
|
|
IoManager.Instance.GetDoBuffer(pmSource)[bufferIndex][index] = (bool)value;
|
2026-05-21 15:23:06 +08:00
|
|
|
|
break;
|
2026-06-05 09:59:19 +08:00
|
|
|
|
case "AI":
|
|
|
|
|
|
IoManager.Instance.GetAiBuffer(pmSource)[bufferIndex][index] = (float)value;
|
2026-03-24 15:04:02 +08:00
|
|
|
|
break;
|
2026-06-05 09:59:19 +08:00
|
|
|
|
case "AO":
|
|
|
|
|
|
IoManager.Instance.GetAoBuffer(pmSource)[bufferIndex][index] = (float)value;
|
2026-05-21 15:23:06 +08:00
|
|
|
|
break;
|
2026-03-24 15:04:02 +08:00
|
|
|
|
}
|
2026-06-05 09:59:19 +08:00
|
|
|
|
|
2026-03-24 15:04:02 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool[] ReadDi(int offset, int size, out string reason)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new System.NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public float[] ReadAiFloat(int offset, int size, out string reason)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new System.NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public int[] ReadAiInt(int offset, int size, out string reason)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new System.NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool WriteDo(int offset, bool[] buffer, out string reason)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new System.NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool WriteAoFloat(int offset, float[] buffer, out string reason)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new System.NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool WriteAoInt(int offset, int[] buffer, out string reason)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new System.NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public int Heartbeat(int counter)
|
|
|
|
|
|
{
|
|
|
|
|
|
return counter;
|
|
|
|
|
|
}
|
2026-06-05 09:59:19 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// GVL_IO.PM{n}_{DI|DO|AI|AO}_G[_N] => PM{n}.PLC, type, index (N-1, default 0)
|
|
|
|
|
|
private static bool TryParseIoVariable(string variable, out string pmSource, out string ioType, out int bufferIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
pmSource = null;
|
|
|
|
|
|
ioType = null;
|
|
|
|
|
|
bufferIndex = 0;
|
|
|
|
|
|
|
|
|
|
|
|
var dotIndex = variable.LastIndexOf('.');
|
|
|
|
|
|
if (dotIndex < 0)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
var name = variable.Substring(dotIndex + 1);
|
|
|
|
|
|
var pmEnd = name.IndexOf('_');
|
|
|
|
|
|
if (pmEnd <= 2 || !name.StartsWith("PM"))
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
pmSource = name.Substring(0, pmEnd) + ".PLC";
|
|
|
|
|
|
var rest = name.Substring(pmEnd + 1);
|
|
|
|
|
|
|
|
|
|
|
|
if (rest.StartsWith("DI_")) ioType = "DI";
|
|
|
|
|
|
else if (rest.StartsWith("DO_")) ioType = "DO";
|
|
|
|
|
|
else if (rest.StartsWith("AI_")) ioType = "AI";
|
|
|
|
|
|
else if (rest.StartsWith("AO_")) ioType = "AO";
|
|
|
|
|
|
else return false;
|
|
|
|
|
|
|
|
|
|
|
|
const string groupMarker = "_G";
|
|
|
|
|
|
var gIndex = rest.LastIndexOf(groupMarker, StringComparison.Ordinal);
|
|
|
|
|
|
if (gIndex < 0)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
var indexPart = rest.Substring(gIndex + groupMarker.Length);
|
|
|
|
|
|
if (indexPart.Length == 0)
|
|
|
|
|
|
bufferIndex = 0;
|
|
|
|
|
|
else if (indexPart.StartsWith("_") && int.TryParse(indexPart.Substring(1), out var suffixNum))
|
|
|
|
|
|
bufferIndex = suffixNum - 1;
|
|
|
|
|
|
else
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-24 15:04:02 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|