Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Core/IoProviders/Mitsubishis/MYMCProtocolPlc.cs

472 lines
16 KiB
C#

using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Log;
using MECF.Framework.Common.Communications;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace MECF.Framework.RT.Core.IoProviders
{
public class MYMCProtocolPlc : IoProvider, IConnection
{
private string _ip = "127.0.0.1";
private string _localIp = "127.0.0.1";
private int _port = 6731;
private int _socketId = 101;
private int _stationId = 102;
private byte[] _bufferIn;
private byte[] _bufferOut;
private int _bufferSize = 2048;
private MCProtocol.MC_COMMAND_HEADER _header;
//private MCProtocol.MC_RESPONSE_HEADER _response;
private MCProtocol.MC_BATCH_COMMAND _batchCommand;
private MCSocket _socket;
private int perIoLength = 960;
public string Address
{
get { return $"{_ip}:{_port}"; }
}
public bool IsConnected
{
get { return IsOpened; }
}
public bool Connect()
{
return true;
}
public bool Disconnect()
{
return true;
}
protected override void Close()
{
_socket.Close();
SetState(IoProviderStateEnum.Closed);
}
protected override void Open()
{
_socket = new MCSocket();
_header = new MCProtocol.MC_COMMAND_HEADER()
{
ProtocolID = MCProtocol.MC_SUBHEADER_COMMAND_MESSAGE,
NetworkID = (byte)_socketId,
StationID = (byte)_stationId,
RequestIONumber = MCProtocol.MC_REQUEST_MODULE_IO_NUMBER,
RequestStationNumber = MCProtocol.MC_REQUEST_MODULE_STATION_NUMBER,
RequestDataLen = 0,
CPUMonitorTimer = (ushort)(MCProtocol.MC_CPU_MONITOR_TIMER * 2),
};
_batchCommand = new MCProtocol.MC_BATCH_COMMAND()
{
Command = MCProtocol.MC_COMMAND_BATCH_READ,
DeviceCode = MCProtocol.MC_DEVICE_CODE_DATA_REGISTER_WORD,
DevicePoints = 0,
HeadAddr = 0,
Reserved = 0,
SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS,
};
_bufferOut = new byte[_bufferSize];
_bufferIn = new byte[_bufferSize];
_socket.Open(_ip, _port, _localIp);
SetState(IoProviderStateEnum.Opened);
}
protected override short[] ReadAi(int offset, int size)
{
short[] buff = new short[size];
int count = size / perIoLength;
if (count < 1)
{
short[] aibuffer = DoReadAi(offset, size);
if (aibuffer != null)
Array.Copy(aibuffer, 0, buff, 0, aibuffer.Length);
}
else
{
short[] aibuffer;
for (int i = 0; i < count; i++)
{
aibuffer = DoReadAi(i * perIoLength + offset, perIoLength);
if (aibuffer != null)
Array.Copy(aibuffer, 0, buff, i * perIoLength, aibuffer.Length);
}
if (size % perIoLength != 0)
{
aibuffer = DoReadAi(offset + perIoLength * count, size % perIoLength);
if (aibuffer != null)
Array.Copy(aibuffer, 0, buff, size - size % perIoLength, aibuffer.Length);
}
}
return buff;
}
protected short[] DoReadAi(int offset, int size)
{
_batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_READ;
_batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS;
_batchCommand.HeadAddr = (ushort)(offset & 0xFFFF);
_batchCommand.Reserved = (byte)(offset >> 16);
_batchCommand.DevicePoints = (ushort)size;
_header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE);
byte[] buffer = MCProtocol.Struct2Bytes(_header);
byte[] command = MCProtocol.Struct2Bytes(_batchCommand);
Array.Copy(buffer, 0, _bufferOut, 0, buffer.Length);
Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length);
if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE))
{
return null;
}
if (!ReceiveData(_bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE))
{
return null;
}
MCProtocol.MC_RESPONSE_HEADER responseHeader =
MCProtocol.ToStruct<MCProtocol.MC_RESPONSE_HEADER>(_bufferIn);
if (responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS)
{
return null;
}
int dataLength = responseHeader.ResponseDataLen - MCProtocol.JUNK_SIZE;
if (!ReceiveData(_bufferIn, dataLength))
{
return null;
}
int sizeofT1 = Marshal.SizeOf(typeof(byte));
int sizeofT2 = Marshal.SizeOf(typeof(ushort));
short[] result = new short[sizeofT1 * 2 / sizeofT2];
for (int i = 0; i < result.Length; i++)
{
result[i] = (short)BitConverter.ToUInt16(_bufferIn, i * 2);
}
return Array.ConvertAll(MCProtocol.Byte2Ushort(_bufferIn, 0, dataLength), x => (short)x);
}
protected override bool[] ReadDi(int offset, int size)
{
bool[] buff = new bool[size];
int count = size / perIoLength;
if (count < 1)
{
bool[] dibuffer = DoReadDi(offset, size);
if (dibuffer != null)
Array.Copy(dibuffer, 0, buff, 0, dibuffer.Length);
}
else
{
bool[] dibuffer;
for (int i = 0; i < count; i++)
{
dibuffer = DoReadDi(i * perIoLength + offset, perIoLength);
if (dibuffer != null)
Array.Copy(dibuffer, 0, buff, i * perIoLength, dibuffer.Length);
}
if (size % perIoLength != 0)
{
dibuffer = DoReadDi(offset + perIoLength * count, size % perIoLength);
if (dibuffer != null)
Array.Copy(dibuffer, 0, buff, size - size % perIoLength, dibuffer.Length);
}
}
return buff;
}
protected bool[] DoReadDi(int offset, int size)
{
_batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_READ;
_batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_BIT_UNITS;
_batchCommand.HeadAddr = (ushort)(offset & 0xFFFF);
_batchCommand.Reserved = (byte)(offset >> 16);
_batchCommand.DevicePoints = (ushort)size;
_header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE);
byte[] buffer = MCProtocol.Struct2Bytes(_header);
byte[] command = MCProtocol.Struct2Bytes(_batchCommand);
Array.Copy(buffer, 0, _bufferOut, 0, buffer.Length);
Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length);
if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE))
{
return null;
}
if (!ReceiveData(_bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE))
{
return null;
}
MCProtocol.MC_RESPONSE_HEADER responseHeader =
MCProtocol.ToStruct<MCProtocol.MC_RESPONSE_HEADER>(_bufferIn);
if (responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS)
{
return null;
}
int dataLength = responseHeader.ResponseDataLen - MCProtocol.JUNK_SIZE;
if (!ReceiveData(_bufferIn, dataLength))
{
return null;
}
byte[] result = new byte[dataLength * 2];
for (int i = 0; i < dataLength; i++)
{
if ((_bufferIn[i] & 0x10) == 0x10)
{
result[i * 2 + 0] = 0x01;
}
if ((_bufferIn[i] & 0x01) == 0x01)
{
result[i * 2 + 1] = 0x01;
}
}
return result.Select(x => x == 0x01).Take(size).ToArray();
}
protected override void SetParameter(XmlElement nodeParameter)
{
string strIp = nodeParameter.GetAttribute("ip");
string strPort = nodeParameter.GetAttribute("port");
string networkId = nodeParameter.GetAttribute("network_id");
string stationId = nodeParameter.GetAttribute("station_id");
if (!string.IsNullOrEmpty(nodeParameter.GetAttribute("buffer_size")))
{
int.TryParse(nodeParameter.GetAttribute("buffer_size"), out _bufferSize);
}
_port = int.Parse(strPort);
_ip = strIp;
_socketId = int.Parse(networkId);
_stationId = int.Parse(stationId);
ConnectionManager.Instance.Subscribe(Name, this);
DATA.Subscribe($"{Module}.{Name}.IsConnected", () => _socket == null ? false : _socket.Connected);
}
protected override void WriteAo(int offset, short[] data)
{
short[] databuffer = new short[perIoLength];
int count = data.Length / perIoLength;
if (count < 1)
{
Array.Copy(data, 0, databuffer, 0, data.Length);
Array.Resize(ref databuffer, data.Length);
DoWriteAo(offset, databuffer.Select(x => (ushort)x).ToArray());
}
else
{
for (int i = 0; i < count; i++)
{
Array.Copy(data, i * perIoLength, databuffer, 0, databuffer.Length);
DoWriteAo(offset + perIoLength * i, databuffer.Select(x => (ushort)x).ToArray());
}
if (data.Length % perIoLength != 0)
{
Array.Copy(data, perIoLength * count, databuffer, 0, data.Length % perIoLength);
Array.Resize(ref databuffer, data.Length % perIoLength);
DoWriteAo(offset + perIoLength * count, databuffer.Select(x => (ushort)x).ToArray());
}
}
}
protected override void ReadDo(int offset, bool[] buffer)
{
throw new NotImplementedException();
}
protected override short[] ReadAo(int offset, int size)
{
throw new NotImplementedException();
}
protected void DoWriteAo(int offset, ushort[] data)
{
_batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_WRITE;
_batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_WORD_UNITS;
_batchCommand.HeadAddr = (ushort)(offset & 0xFFFF);
_batchCommand.Reserved = (byte)(offset >> 16);
_batchCommand.DevicePoints = (ushort)data.Length;
_header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE + MCProtocol.ShortSize * data.Length);
byte[] header = MCProtocol.Struct2Bytes(_header);
byte[] command = MCProtocol.Struct2Bytes(_batchCommand);
byte[] byteData = MCProtocol.Ushort2Byte(data);
Array.Copy(header, 0, _bufferOut, 0, header.Length);
Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length);
Array.Copy(byteData, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE, byteData.Length);
if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.ShortSize * data.Length))
{
return;
}
if (!ReceiveData(_bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE))
{
return;
}
MCProtocol.MC_RESPONSE_HEADER responseHeader =
MCProtocol.ToStruct<MCProtocol.MC_RESPONSE_HEADER>(_bufferIn);
if (responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS)
{
LOG.Write("Write PLC failed with code," + responseHeader.CompleteCode);
return;
}
int dataLength = responseHeader.ResponseDataLen - MCProtocol.JUNK_SIZE;
if (dataLength > 0 && !ReceiveData(_bufferIn, dataLength))
{
return;
}
}
protected override void WriteDo(int offset, bool[] data)
{
bool[] databuffer = new bool[perIoLength];
int count = data.Length / perIoLength;
if (count < 1)
{
Array.Copy(data, 0, databuffer, 0, data.Length);
Array.Resize(ref databuffer, data.Length);
DoWriteDo(offset, databuffer);
}
else
{
for (int i = 0; i < count; i++)
{
Array.Copy(data, i * perIoLength, databuffer, 0, databuffer.Length);
DoWriteDo(offset + perIoLength * i, databuffer);
}
if (data.Length % perIoLength != 0)
{
Array.Copy(data, perIoLength * count, databuffer, 0, data.Length % perIoLength);
Array.Resize(ref databuffer, data.Length % perIoLength);
DoWriteDo(offset + perIoLength * count, databuffer);
}
}
}
protected void DoWriteDo(int offset, bool[] data)
{
// bool[] boolData = new bool[data.Length];
// boolData = data.Select(x => x==(byte)1).ToArray();
// WriteDo(offset, boolData);
//}
//protected void WriteDo(int offset, bool[] data)
//{
_batchCommand.Command = MCProtocol.MC_COMMAND_BATCH_WRITE;
_batchCommand.SubCommand = MCProtocol.MC_SUBCOMMAND_BIT_UNITS;
byte[] byteData = MCProtocol.TransBoolArrayToByteData(data);
_batchCommand.HeadAddr = (ushort)(offset & 0xFFFF);
_batchCommand.Reserved = (byte)(offset >> 16);
_batchCommand.DevicePoints = (ushort)data.Length;
_header.RequestDataLen = (ushort)(MCProtocol.MC_BATCH_COMMAND_SIZE + MCProtocol.JUNK_SIZE + byteData.Length);
byte[] header = MCProtocol.Struct2Bytes(_header);
byte[] command = MCProtocol.Struct2Bytes(_batchCommand);
Array.Copy(header, 0, _bufferOut, 0, header.Length);
Array.Copy(command, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE, command.Length);
Array.Copy(byteData, 0, _bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE, byteData.Length);
if (!WriteData(_bufferOut, MCProtocol.MC_QHEADER_COMMAND_SIZE + MCProtocol.MC_BATCH_COMMAND_SIZE + byteData.Length))
{
return;
}
if (!ReceiveData(_bufferIn, MCProtocol.MC_QHEADER_RESPONSE_SIZE))
{
return;
}
MCProtocol.MC_RESPONSE_HEADER responseHeader =
MCProtocol.ToStruct<MCProtocol.MC_RESPONSE_HEADER>(_bufferIn);
if (responseHeader.CompleteCode != MCProtocol.MC_COMPLETE_CODE_SUCCESS)
{
LOG.Write("Write PLC failed with code," + responseHeader.CompleteCode);
return;
}
int dataLength = responseHeader.ResponseDataLen - MCProtocol.JUNK_SIZE;
if (dataLength > 0 && !ReceiveData(_bufferIn, dataLength))
{
return;
}
}
private bool WriteData(byte[] data, int length)
{
return _socket.Write(data, length);
}
private bool ReceiveData(byte[] data, int length)
{
return _socket.Read(data, length);
}
}
}