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