MoS2/Framework/MECF.Framework.RT.EquipmentLibrary/Devices/SiemensIoProvider.cs
2026-06-15 10:56:30 +08:00

485 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Aitex.Core.RT.IOCore;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using MECF.Framework.Common.PLC;
using MECF.Framework.RT.Core.IoProviders;
using System;
using System.Diagnostics;
using System.Xml;
namespace Aitex.Core.RT.Device.Devices
{
public partial class SiemensIoProvider : IoProvider
{
protected readonly DOAccessor _doShutDown;
private IAdsPlc _ads;
private static object _locker = new object();
private R_TRIG _trigConnected = new R_TRIG();
protected override void SetParameter(XmlElement nodeParameter)
{
}
private bool MonitorAdsConnection()
{
//if (_SiemensClient == null)
//{
// _SiemensClient = DEVICE.GetDevice<PMModule>(Module + "." + Module)?.Siemens;
//}
//if (_SiemensClient != null) return _SiemensClient.IsTrue;
//return false;
if (_ads == null)
{
_ads = DEVICE.GetOptionDevice($"{Module}.MainPLC", typeof(SicAds)) as IAdsPlc;
}
return _ads != null && _ads.CheckIsConnected();
}
//public bool IsCommunicationError
//{
// get { return _ads.IsCommunicationError; }
//}
protected override void Close()
{
}
protected override void Open()
{
}
protected override bool OnTimer()
{
_trigConnected.CLK = MonitorAdsConnection();
if (!_trigConnected.M)
return true;
lock (_locker)
{
// PLC数据以32位二级制存储软件读取的值与DINT相同
// 如果是DINT类型数据直接使用无需转换
// 如果是REAL类型数据先使用BitConverter.GetBytes获取有4个元素的字节数组再使用BitConverter.ToSingle得到float类型值
// 如果是DWORD类型数据先使用BitConverter.GetBytes获取有4个元素的字节数组再进行位运算得到每位的值
//int[] input = ReadInput();
//Console.WriteLine(input[0]);
//byte[] byteArr = BitConverter.GetBytes(input[0]);
//float fValve = BitConverter.ToSingle(byteArr, 0);
foreach (var key in DiVariables.Keys)
{
var ioVar = DiVariables[key];
var diData = ReadDIn(ioVar.Name, (ushort)ioVar.Length);
if (diData != null)
{
var diBuffer = ParseDI(key, diData);
if (diBuffer != null)
{
_buffer.SetDiBuffer(_source, ioVar.Block.Index, diBuffer);
}
}
}
foreach (var key in DoVariables.Keys)
{
var ioVar = DoVariables[key];
var doData = ReadDOut(ioVar.Name, (ushort)ioVar.Length);
if (doData != null)
{
var doBuffer = ParseDO(key, doData);
if (doBuffer != null)
{
_buffer.SetDoBuffer(_source, ioVar.Block.Index, doBuffer);
}
}
}
foreach (var key in AiVariables.Keys)
{
var ioVar = AiVariables[key];
var aiData = ReadAIn(ioVar.Name, (ushort)ioVar.Length);
if (aiData != null)
{
var aiBuffer = ParseAI(key, aiData);
if (aiBuffer != null)
{
_buffer.SetAiBuffer(_source, ioVar.Block.Index, aiBuffer);
}
}
}
foreach (var key in AoVariables.Keys)
{
var ioVar = AoVariables[key];
var aoData = ReadAOut(ioVar.Name, (ushort)ioVar.Length);
if (aoData != null)
{
var aoBuffer = ParseAO(key, aoData);
if (aoBuffer != null)
{
_buffer.SetAoBuffer(_source, ioVar.Block.Index, aoBuffer);
}
}
}
}
return true;
}
private bool CommunicationError()
{
//_buffer.SetDiBuffer(_source, 0, new bool[1000]);
//_buffer.SetDoBuffer(_source, 0, new bool[1000]);
//_buffer.SetAiBufferFloat(_source, 0, new float[1000]);
//_buffer.SetAoBufferFloat(_source, 0, new float[1000]);
return true;
}
protected byte[] ReadDIn(string variable, ushort len)
{
if (!_trigConnected.M)
return null;
if (_ads.BulkReadRenderResult(variable, len, out var data))
return data;
return null;
}
private byte[] ReadDOut(string variable, ushort len)
{
if (!_trigConnected.M)
return null;
if (_ads.BulkReadRenderResult(variable, len, out var data))
return (byte[])data;
return null;
}
protected byte[] ReadAIn(string variable, ushort len)
{
if (!_trigConnected.M)
return null;
if (_ads.BulkReadRenderResult(variable, len, out var data))
return data;
return null;
}
private byte[] ReadAOut(string variable, ushort len)
{
if (!_trigConnected.M)
return null;
if (_ads.BulkReadRenderResult(variable, len, out var data))
return (byte[])data;
return null;
}
private bool[] ParseDI(int blockIndex, byte[] inputValue)
{
var dataCount = inputValue.Length * 8;
var result = new bool[dataCount];
for (var i = 0; i < dataCount; i++)
{
var whichBit = i % 8;
var whichByte = i % 8 == 0 ? i / 8 : (i - i % 8) / 8;
result[i] = ((inputValue[whichByte] >> whichBit) & 0x1) == 1;
}
return result;
}
private bool[] ParseDO(int blockIndex, byte[] outputValue)
{
var dataCount = outputValue.Length * 8;
var result = new bool[dataCount];
for (var i = 0; i < dataCount; i++)
{
var whichBit = i % 8;
var whichByte = i % 8 == 0 ? i / 8 : (i - i % 8) / 8;
result[i] = ((outputValue[whichByte] >> whichBit) & 0x1) == 1;
}
return result;
}
private float[] ParseAI(int blockIndex, byte[] inputValue)
{
Debug.Assert(inputValue.Length % 4 == 0, "The length of 'inputValue' must be 4-byte align");
var dataCount = inputValue.Length / 4;
var result = new float[dataCount];
for (var i = 0; i < dataCount; i++)
{
if (blockIndex == 0)
{
var index = i;
if (index <= 71 || index >= 108 && index <= 117 || index >= 181 || index == 119 || index == 123 || index == 124 || index == 125)
{
if (index >= 181)
index += 181; // 跳过181个AO
result[i] = BitConverter.ToSingle([inputValue[index * 4 + 3], inputValue[index * 4 + 2], inputValue[index * 4 + 1], inputValue[index * 4]
], 0);
}
else if (index >= 72 && index <= 103)
{
result[i] = BitConverter.ToSingle([inputValue[index * 4 + 3], inputValue[index * 4 + 2], inputValue[index * 4 + 1], inputValue[index * 4]
], 0);
}
else if (index >= 104 && index <= 107 || index >= 118 && index <= 128)
{
result[i] = BitConverter.ToUInt32([inputValue[index * 4 + 3], inputValue[index * 4 + 2], inputValue[index * 4 + 1], inputValue[index * 4]
], 0);
}
else if (index == 129)
{
result[i] = BitConverter.ToSingle([inputValue[index * 4 + 3], inputValue[index * 4 + 2], inputValue[index * 4 + 1], inputValue[index * 4]
], 0);
}
else if (index >= 130 && index <= 180)
{
result[i] = BitConverter.ToInt32([inputValue[index * 4 + 3], inputValue[index * 4 + 2], inputValue[index * 4 + 1], inputValue[index * 4]
], 0);
}
}
else
{
result[i] = BitConverter.ToSingle([
inputValue[i * 4 + 3],
inputValue[i * 4 + 2],
inputValue[i * 4 + 1],
inputValue[i * 4]
], 0);
}
}
return result;
/* var aiList = Singleton<IoManager>.Instance.GetAIList($"{Module}.io").Where(x=>x.BlockIndex == blockIndex);
var result = new float[500];
foreach (var aiAccessor in aiList)
{
var addr = aiAccessor.Addr;
if (int.TryParse(addr, out var index))
{
var valve = BitConverter.ToSingle([
inputValue[index * 4 + 3],
inputValue[index * 4 + 2],
inputValue[index * 4 + 1],
inputValue[index * 4]
], 0);
result[aiAccessor.Index] = valve;
}
}
return result;*/
}
private float[] ParseAO(int blockIndex, byte[] outputValue)
{
Debug.Assert(outputValue.Length % 4 == 0, "The length of 'outputValue' must be 4-byte align");
var dataCount = outputValue.Length / 4;
var result = new float[dataCount];
for (var i = 0; i < dataCount; i++)
{
if (blockIndex == 0)
{
var index = i;
var valve = 0.0f;
if (index >= 92 && index <= 103)
{
valve = BitConverter.ToSingle([outputValue[index * 4 + 3], outputValue[index * 4 + 2], outputValue[index * 4 + 1], outputValue[index * 4]
], 0);
}
else if (index >= 104 && index <= 107)
{
valve = BitConverter.ToSingle([outputValue[index * 4 + 3], outputValue[index * 4 + 2], outputValue[index * 4 + 1], outputValue[index * 4]
], 0);
}
else if (index <= 117 || index >= 181 || index == 129 || index == 122 || index == 123 || index == 124 || index == 125)
{
if (index >= 181)
index += 100; // 跳过100个AI
valve = BitConverter.ToSingle([outputValue[index * 4 + 3], outputValue[index * 4 + 2], outputValue[index * 4 + 1], outputValue[index * 4]
], 0);
}
else if (index >= 118 && index <= 128 && index != 119)
{
valve = BitConverter.ToUInt32([outputValue[index * 4 + 3], outputValue[index * 4 + 2], outputValue[index * 4 + 1], outputValue[index * 4]
], 0);
}
else if (index >= 130 && index <= 180)
{
valve = BitConverter.ToInt32([outputValue[index * 4 + 3], outputValue[index * 4 + 2], outputValue[index * 4 + 1], outputValue[index * 4]
], 0);
}
result[i] = valve;
}
else
{
result[i] = BitConverter.ToSingle([
outputValue[i * 4 + 3],
outputValue[i * 4 + 2],
outputValue[i * 4 + 1],
outputValue[i * 4]
], 0);
}
}
return result;
}
protected override short[] ReadAi(int offset, int size)
{
throw new NotImplementedException();
}
protected override bool[] ReadDi(int offset, int size)
{
throw new NotImplementedException();
}
protected override void WriteAo(int offset, short[] buffer)
{
throw new NotImplementedException();
}
protected override void ReadDo(int offset, bool[] buffer)
{
throw new NotImplementedException();
}
protected override short[] ReadAo(int offset, int size)
{
throw new NotImplementedException();
}
protected override void WriteDo(int offset, bool[] buffer)
{
throw new NotImplementedException();
}
public override bool SetValue(AOAccessor aoItem, float value)
{
if (!_trigConnected.M)
return false;
lock (_locker)
{
var data = new byte[4];
//// 获取下标转换成Byte数组然后写下去
var addr = aoItem.Addr;
var index = int.Parse(addr);
var ioVar = AoVariables[aoItem.BlockIndex];
// Address: DB100.DBDxxx
// target: xxx +index
var stringSeparators = new string[] { "DBD" };
var result = ioVar.Name.Split(stringSeparators, StringSplitOptions.None);
int.TryParse(result[1], out var startIndex);
var finalIndex = startIndex + index * sizeof(float); // 4 bytes per data
var address = $"{result[0]}DBD{finalIndex}";
if (aoItem.BlockIndex == 0)
{
if (index >= 92 && index <= 103)
{
data = BitConverter.GetBytes(value);
}
else if (index <= 117 || index >= 181 || index == 129 || index == 119 || index == 122 || index == 123 || index == 124 || index == 125)
{
data = BitConverter.GetBytes(value);
}
else if (index >= 118 && index <= 128)
{
data = BitConverter.GetBytes((uint)value);
}
else if (index >= 130 && index <= 180)
{
data = BitConverter.GetBytes((int)value);
}
}
else
{
data = BitConverter.GetBytes(value);
}
Array.Reverse(data);
return _ads.BulkWriteByteRenderResult(address, data);
}
}
public override bool SetValue(DOAccessor doItem, bool value)
{
if (!_trigConnected.M)
{
return false;
}
if (!IO.CanSetDO(doItem.Name, value, out var reason))
{
LOG.Write(reason);
return false;
}
lock (_locker)
{
var ioVar = DoVariables[doItem.BlockIndex];
////获取单个DWORD数据修改其中一位然后整个Byte写下去
var addr = doItem.Addr;
var add = int.Parse(addr);
var indexByte = add % 8;
var index = add % 8 == 0 ? add / 8 : (add - add % 8) / 8;
var val = 1 << indexByte;
var output = ReadDOut(ioVar.Name, (ushort)ioVar.Length);
if (output == null)
{
LOG.Write("ReadDOut = null , in SetValue()");
return false;
}
output[index] = value
? Convert.ToByte(Convert.ToUInt16(output[index]) | val)
: Convert.ToByte((Convert.ToUInt16(output[index]) & ~val));
var stringSeparators = new string[] { "DBB" };
var result = ioVar.Name.Split(stringSeparators, StringSplitOptions.None);
int.TryParse(result[1], out var startIndex);
var finalIndex = startIndex + index;
var address = $"{result[0]}DBB{finalIndex}";
var data = new byte[] { output[index] };
return _ads.BulkWriteByteRenderResult(address, data);
}
}
}
}