using System; using System.Collections.Generic; using System.Net; using System.Runtime.InteropServices; using TouchSocket.Core.ByteManager; using TouchSocket.Sockets; namespace Rdh.SocketServer.Client.Models { public class RfidUdpDataHandlingAdapter : UdpDataHandlingAdapter { public override bool CanSendRequestInfo => false; public override bool CanSplicingSend => false; public int HeaderLength => 5; /// /// 临时包,此包仅当前实例储存 /// private ByteBlock tempByteBlock; /// /// 包剩余长度 /// private byte surPlusLength; protected override void PreviewReceived(EndPoint remoteEndPoint, ByteBlock byteBlock) { byte[] buffer = byteBlock.Buffer; int r = byteBlock.Len; if (this.tempByteBlock == null)//如果没有临时包,则直接分包。 { SplitPackage(remoteEndPoint, buffer, 0, r); } else { if (surPlusLength == r)//接收长度正好等于剩余长度,组合完数据以后直接处理数据。 { this.tempByteBlock.Write(buffer, 0, surPlusLength); PreviewHandle(remoteEndPoint, this.tempByteBlock); this.tempByteBlock = null; surPlusLength = 0; } else if (surPlusLength < r)//接收长度大于剩余长度,先组合包,然后处理包,然后将剩下的分包。 { this.tempByteBlock.Write(buffer, 0, surPlusLength); PreviewHandle(remoteEndPoint, this.tempByteBlock); this.tempByteBlock = null; SplitPackage(remoteEndPoint, buffer, surPlusLength, r); } else//接收长度小于剩余长度,无法处理包,所以必须先组合包,然后等下次接收。 { this.tempByteBlock.Write(buffer, 0, r); surPlusLength -= (byte)r; } } } /// /// 分解包 /// /// /// /// private void SplitPackage(EndPoint remoteEndPoint, byte[] dataBuffer, int index, int r) { while (index < r) { byte length = dataBuffer[index]; int recedSurPlusLength = r - index - 1; if (recedSurPlusLength >= length) { ByteBlock byteBlock = BytePool.GetByteBlock(length); byteBlock.Write(dataBuffer, index + 1, length); PreviewHandle(remoteEndPoint, byteBlock); surPlusLength = 0; } else//半包 { this.tempByteBlock = BytePool.GetByteBlock(length); surPlusLength = (byte)(length - recedSurPlusLength); this.tempByteBlock.Write(dataBuffer, index + 1, recedSurPlusLength); } index += length + 1; } } /// /// 处理数据 /// /// private void PreviewHandle(EndPoint remoteEndPoint, ByteBlock byteBlock) { try { var requestInfo = new RfidFixedHeaderRequestInfo(); byteBlock.Read(out byte[] header, this.HeaderLength); requestInfo.OnParsingHeader(header); byteBlock.Read(out byte[] body, requestInfo.BodyLength); requestInfo.OnParsingBody(body); this.GoReceived(remoteEndPoint, byteBlock, requestInfo); } finally { byteBlock.Dispose();//在框架里面将内存块释放 } } protected override void Reset() { } protected override void PreviewSend(EndPoint endPoint, byte[] buffer, int offset, int length, bool isAsync) { this.GoSend(endPoint, buffer, offset, length, isAsync); } protected override void PreviewSend(IRequestInfo requestInfo, bool isAsync) { } protected override void PreviewSend(EndPoint endPoint, IList> transferBytes, bool isAsync) { throw new System.NotImplementedException(); } } public class RfidFixedHeaderRequestInfo : IFixedHeaderRequestInfo { private const int head = 0xA5; /// /// 数据包头 /// public static int Head { get { return head; } } private int bodyLength; public int BodyLength { get { return bodyLength; } } private byte[] reserved; /// /// 485地址码 /// public byte[] Reserved { get { return reserved; } } private int cmd; /// /// 指令码 /// public int CMD { get { return cmd; } } private byte[] header; public byte[] Header { get { return header; } } private byte[] body; public byte[] Body { get { return body; } } public bool OnParsingBody(byte[] body) { this.bodyLength = body.Length; this.body = body; return true; } public bool OnParsingHeader(byte[] header) { if (header.Length == 5 && header[0] == 0xA5) { this.bodyLength = header[1]; this.reserved = new byte[2]; Buffer.BlockCopy(header, 2, this.reserved, 0, 2); this.cmd = header[4]; this.header = header; return true; } return false; } } [StructLayout(LayoutKind.Sequential)] public struct MtBarcodeResponseProtocol { #region Properties /// /// 起始位 /// public Byte Head { get { return 0xA5; } } /// /// Length(不含)之后的数据长度 /// public Byte Length { get; set; } /// /// 低字节在前,高字节在后 /// public UInt16 Password { get; set; } /// /// 指令码 /// public Byte Command { get; set; } /// /// 0x01:数据包标识 /// public Byte Flags { get; set; } /// /// 读取的频点 /// public Byte Frequency { get; set; } /// /// 天线号 /// public Byte Anntennea { get; set; } /// /// 标签的 PC 协议控制字,固定 2Byte /// public UInt16 PC { get; set; } /// /// 标签的 EPC 号(条码),长度可变化 /// public String EPC { get; set; } /// /// 标签的 CRC,固定 2Byte /// public UInt16 CRC { get; set; } /// /// 标签的实时 RSSI,固定 2Byte /// public UInt16 RSSI { get; set; } /// /// 校验和(除校验本身以外所有字节求和后,按位取反,再加 1) /// public Byte Check { get; set; } #endregion public Byte[] GetBytes() { return StructToBytes(this); } public override string ToString() { return ToString(" "); } public String ToString(String seperator) { return String.Join(seperator, GetBytes()); } public static MtBarcodeResponseProtocol? ReadFromBytes(Byte[] source, Int32 dataLength) { if (dataLength < 16 || source.Length < 16) { return null; } MtBarcodeResponseProtocol rlt = new MtBarcodeResponseProtocol(); rlt.Length = source[1]; rlt.Password = (UInt16)(source[2] | (source[3] << 8)); rlt.Command = source[4]; rlt.Flags = source[5]; rlt.Frequency = source[6]; rlt.Anntennea = source[7]; rlt.PC = (UInt16)(source[8] | (source[9] << 8)); Int32 epcDataLength = rlt.Length - 13; for (Int32 i = 0; i < epcDataLength; i++) { rlt.EPC += source[10 + i].ToString("X2"); } rlt.Check = source[dataLength - 1]; rlt.RSSI = (UInt16)(source[dataLength - 2] << 8 | source[dataLength - 3]); rlt.CRC = (UInt16)(source[dataLength - 4] | source[dataLength - 5]); return rlt; } public static MtBarcodeResponseProtocol? ReadFromBytes(Byte[] source) { var dataLength = source.Length; if (dataLength < 16 || source.Length < 16) { return null; } MtBarcodeResponseProtocol rlt = new MtBarcodeResponseProtocol(); rlt.Length = source[1]; rlt.Password = (UInt16)(source[2] | (source[3] << 8)); rlt.Command = source[4]; rlt.Flags = source[5]; rlt.Frequency = source[6]; rlt.Anntennea = source[7]; rlt.PC = (UInt16)(source[8] | (source[9] << 8)); Int32 epcDataLength = rlt.Length - 13; for (Int32 i = 0; i < epcDataLength; i++) { rlt.EPC += source[10 + i].ToString("X2"); } rlt.Check = source[dataLength - 1]; rlt.RSSI = (UInt16)(source[dataLength - 2] << 8 | source[dataLength - 3]); rlt.CRC = (UInt16)(source[dataLength - 4] | source[dataLength - 5]); return rlt; } public static byte[] StructToBytes(T structObj) { int size = Marshal.SizeOf(structObj); IntPtr buffer = Marshal.AllocHGlobal(size); try { Marshal.StructureToPtr(structObj, buffer, false); byte[] bytes = new byte[size]; Marshal.Copy(buffer, bytes, 0, size); return bytes; } finally { Marshal.FreeHGlobal(buffer); } } } }