Sic08/Modules/Mainframe/Devices/SiemensIoProvider.cs

366 lines
12 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 System;
using System.Xml;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.IOCore;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using MECF.Framework.Common.IOCore;
using MECF.Framework.Common.PLC;
using MECF.Framework.RT.Core.IoProviders;
namespace SicModules.Devices
{
public class SiemensIoProvider : IoProvider
{
private string _diVariable;
private string _doVariable;
private string _aiVariable;
private string _aoVariable;
private ushort diLength;
private ushort doLength;
private ushort aiLength;
private ushort aoLength;
private IAdsPlc _ads;
private static object _locker = new object();
private R_TRIG _trigConnected = new R_TRIG();
protected override void SetParameter(XmlElement nodeParameter)
{
_diVariable = nodeParameter.GetAttribute("diVariable");
_doVariable = nodeParameter.GetAttribute("doVariable");
_aiVariable = nodeParameter.GetAttribute("aiVariable");
_aoVariable = nodeParameter.GetAttribute("aoVariable");
ushort.TryParse(nodeParameter.GetAttribute("diLength"), out diLength);
ushort.TryParse(nodeParameter.GetAttribute("doLength"), out doLength);
ushort.TryParse(nodeParameter.GetAttribute("aiLength"), out aiLength);
ushort.TryParse(nodeParameter.GetAttribute("aoLength"), out aoLength);
}
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);
var diData = ReadDIn();
//if (IsCommunicationError) return CommunicationError();
if (diData != null)
{
var diBuffer = ParseDI(diData);
if (diBuffer != null)
{
_buffer.SetDiBuffer(_source, 0, diBuffer);
}
}
var doData = ReadDOut();
//if (IsCommunicationError) return CommunicationError();
if (doData != null)
{
var doBuffer = ParseDO(doData);
if (doBuffer != null)
{
_buffer.SetDoBuffer(_source, 0, doBuffer);
}
}
var aiData = ReadAIn();
//if (IsCommunicationError) return CommunicationError();
if (aiData != null)
{
var aiBuffer = ParseAI(aiData);
if (aiBuffer != null)
{
_buffer.SetAiBuffer(_source, 0, aiBuffer);
}
}
var aoData = ReadAOut();
//if (IsCommunicationError) return CommunicationError();
if (aoData != null)
{
var aoBuffer = ParseAO(aoData);
if (aoBuffer != null)
{
_buffer.SetAoBuffer(_source, 0, 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[500]);
//_buffer.SetAoBufferFloat(_source, 0, new float[500]);
return true;
}
protected byte[] ReadDIn()
{
if (!_trigConnected.M)
return null;
if (_ads.BulkReadRenderResult(_diVariable, diLength, out var data))
return data;
return null;
}
private byte[] ReadDOut()
{
if (!_trigConnected.M)
return null;
if (_ads.BulkReadRenderResult(_doVariable, doLength, out var data))
return (byte[])data;
return null;
}
protected byte[] ReadAIn()
{
if (!_trigConnected.M)
return null;
if (_ads.BulkReadRenderResult(_aiVariable, aiLength, out var data))
return data;
return null;
}
private byte[] ReadAOut()
{
if (!_trigConnected.M)
return null;
if (_ads.BulkReadRenderResult(_aoVariable, aoLength, out var data))
return (byte[])data;
return null;
}
private bool[] ParseDI(byte[] inputValue)
{
var diList = Singleton<IoManager>.Instance.GetDIList($"{Module}.io");
var result = new bool[1000];
foreach (var diAccessor in diList)
{
var addr = diAccessor.Addr;
var index = int.Parse(addr);
var Offset = index % 8;
var val = index % 8 == 0 ? index / 8 : (index - index % 8) / 8;
result[diAccessor.Index] = ((inputValue[val] >> Offset) & 0x1) == 1;
}
return result;
}
private bool[] ParseDO(byte[] outputValue)
{
//Addr="OUTPUT[0].4"
var doList = Singleton<IoManager>.Instance.GetDOList($"{Module}.io");
var cache = new bool[1000];
foreach (var doAccessor in doList)
{
var addr = doAccessor.Addr;
var index = int.Parse(addr);
var whichBit = index % 8;
var whichByte = index % 8 == 0 ? index / 8 : (index - index % 8) / 8;
cache[doAccessor.Index] = ((outputValue[whichByte] >> whichBit) & 0x1) == 1;
}
return cache;
}
private float[] ParseAI(byte[] inputValue)
{
var aiList = Singleton<IoManager>.Instance.GetAIList($"{Module}.io");
var result = new float[500];
foreach (var aiAccessor in aiList)
{
var addr = aiAccessor.Addr;
var index = int.Parse(addr);
var valve = BitConverter.ToSingle(new byte[] { 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(byte[] outputValue)
{
//Addr="OUTPUT[30]"
var aoList = Singleton<IoManager>.Instance.GetAOList($"{Module}.io");
var result = new float[500];
foreach (var aoAccessor in aoList)
{
var addr = aoAccessor.Addr;
var index = int.Parse(addr);
var valve = BitConverter.ToSingle(new[]
{
outputValue[index * 4 + 3],
outputValue[index * 4 + 2],
outputValue[index * 4 + 1],
outputValue[index * 4]
},
0);
result[aoAccessor.Index] = valve;
}
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;
//// 获取下标转换成16进制 IEEE 754浮点数然后整个写下去
var addr = aoItem.Addr;
var index = int.Parse(addr);
var address = _aoVariable.Substring(0, 9) + (int.Parse(_aoVariable.Substring(9, 3)) + index * 4);
var data = new byte[4];
if (index <= 48)
{
data = BitConverter.GetBytes(value);
}
else if (index >= 49)
{
data = BitConverter.GetBytes((int)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)
{
////获取单个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();
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 = _doVariable.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);
}
}
}
}